1.0.0
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.hbuilderx
|
||||
unpackage
|
||||
.vscode
|
||||
.idea
|
||||
node_modules
|
68
App.vue
Normal file
@ -0,0 +1,68 @@
|
||||
<script>
|
||||
import { TaAjax } from '@/common/ajax';
|
||||
import { TaCache } from '@/common/cache';
|
||||
import { TaToast } from '@/common/toast';
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
console.log('App Launch')
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success(loginRes) {
|
||||
// 换取会话密钥
|
||||
let data = {
|
||||
code: loginRes.code,
|
||||
iv: '',
|
||||
encrypted: ''
|
||||
}
|
||||
TaAjax.post('/plugin-account/api.wxapp/session', data).then((ret) => {
|
||||
console.log('SessionDone: ', ret)
|
||||
TaCache.set('auth.token', ret.data.token)
|
||||
// 获取用户信息
|
||||
uni.getUserInfo({
|
||||
provider: 'weixin',
|
||||
success: (infoRes) => {
|
||||
console.log('UserInfo: ', infoRes)
|
||||
data.iv = infoRes.iv, data.encrypted = infoRes
|
||||
.encryptedData
|
||||
TaAjax.post('/plugin-account/api.wxapp/decode', data)
|
||||
.then((ret) => {
|
||||
console.log('UserDone: ', ret.data)
|
||||
TaCache.set('auth.user', ret.data)
|
||||
}).catch((ret) => {
|
||||
console.log('UserFail: ', ret.data)
|
||||
})
|
||||
}
|
||||
})
|
||||
}).catch((ret) => {
|
||||
console.log('SessionFail: ', ret)
|
||||
reject(ret);
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/*每个页面公共css */
|
||||
@import '@/uni_modules/uni-scss/index.scss';
|
||||
|
||||
</style>
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
@import '/common/free.css';
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
}
|
||||
page view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
118
common/ajax.js
Normal file
@ -0,0 +1,118 @@
|
||||
import ajax from '@/uni_modules/uni-ajax/js_sdk/index.js';
|
||||
import {
|
||||
TaCache
|
||||
} from './cache';
|
||||
import {
|
||||
TaToast
|
||||
} from './toast';
|
||||
import {
|
||||
objectHasKey
|
||||
} from './util';
|
||||
|
||||
// 执行队列
|
||||
let _tasks = []
|
||||
let _status = true
|
||||
|
||||
export const baseUrl = 'https://www.gafzgc.com/'
|
||||
// export const baseUrl = 'http://127.0.0.1:8000/'
|
||||
|
||||
// 创建请求实例,检查登录状态及业务异常,返回 Body 内容( 建议使用 TaPost 处理)
|
||||
const TaHttp = ajax.create({
|
||||
baseURL: baseUrl
|
||||
})
|
||||
|
||||
// 创建请求实例,不检查登录状态及业务异常,返回 Body 内容
|
||||
export const TaAjax = ajax.create({
|
||||
baseURL: baseUrl
|
||||
})
|
||||
|
||||
// 通用 POST 提交,检查登录状态及业务异常,返回 Body 内容,可中断请求
|
||||
export function TaPost(uri, data = {}, load = '', options = {}) {
|
||||
load.length > 0 && TaToast.loading(load)
|
||||
return new Promise((resolve, reject) => {
|
||||
if (_status) {
|
||||
_tasks.push(options.fetcher = new ajax.Fetcher())
|
||||
TaHttp.post(uri, data, options).then((ret) => {
|
||||
ret.code === 1 ? resolve(ret) : reject(ret)
|
||||
}).finally(() => {
|
||||
load.length > 0 && TaToast.loadhide()
|
||||
_tasks.splice(_tasks.indexOf(options.fetcher), 1)
|
||||
})
|
||||
} else {
|
||||
load.length > 0 && TaToast.loadhide()
|
||||
reject({
|
||||
code: 0,
|
||||
info: '请求已被阻止!'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 阻止 POST 请求 ( 20毫秒内阻止请求 )
|
||||
export function TaPostAbort() {
|
||||
_status = false;
|
||||
_tasks.forEach((x, i) => (x.abort(), _tasks.splice(i, 1)))
|
||||
return new Promise(resolve => setTimeout(() => resolve(_status = true), 20))
|
||||
}
|
||||
|
||||
// 添加请求拦截器
|
||||
TaHttp.interceptors.request.use(useRequestInterceptor, error => Promise.reject(error))
|
||||
TaAjax.interceptors.request.use(useRequestInterceptor, error => Promise.reject(error))
|
||||
|
||||
// 添加响应拦截器
|
||||
TaHttp.interceptors.response.use(response => useResponseInterceptor(response, true), error => Promise.reject(error))
|
||||
TaAjax.interceptors.response.use(response => useResponseInterceptor(response, false), error => Promise.reject(error))
|
||||
|
||||
// 定义请求拦截函数
|
||||
function useRequestInterceptor(config) {
|
||||
// 检查是否有 Api-Token 配置,没有则自动追加配置
|
||||
let token = TaCache.get('auth.token')
|
||||
if (token) config.header['Api-Token'] = token
|
||||
// 检查是否有 Content-Type 配置,没有则自动追加配置
|
||||
if (!objectHasKey(config.header, 'content-type')) {
|
||||
config.header['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// 定义结果拦截函数
|
||||
function useResponseInterceptor(response, checkAuth) {
|
||||
// 获取返回的数据
|
||||
let body = response.data || {
|
||||
code: 0,
|
||||
info: 'unknow',
|
||||
data: {}
|
||||
}
|
||||
// 网络请求异常处理
|
||||
if (response.statusCode === 404) {
|
||||
TaToast.error(body.info || '资源不存在!')
|
||||
return Promise.reject(body)
|
||||
} else if (response.statusCode === 500) {
|
||||
TaToast.error(body.info || '服务异常!')
|
||||
return Promise.reject(body)
|
||||
} else if (response.statusCode !== 200) {
|
||||
TaToast.error(body.info || '请求异常!' + body.code)
|
||||
return Promise.reject(body)
|
||||
}
|
||||
// 接口返回异常处理
|
||||
if (checkAuth) {
|
||||
if (body.code === 402) {
|
||||
TaPostAbort(), TaToast.error(body.info || '请完善资料!').then(() => uni.navigateTo({
|
||||
url: '/pages/user/bind/bind'
|
||||
}))
|
||||
return Promise.reject(body)
|
||||
} else if ((body.code === 401 || body.code === 403)) {
|
||||
TaPostAbort(), TaToast.error(body.info || '需要登录授权!').then(() => DataUser.logout())
|
||||
return Promise.reject(body)
|
||||
} else if (body.code !== 1) {
|
||||
body.info && TaToast.error(body.info)
|
||||
return Promise.reject(body)
|
||||
}
|
||||
}
|
||||
// 任何请求,如果有返回 Token 都进行保存授权令牌
|
||||
if (body.data && typeof body.data.token === 'string') {
|
||||
TaCache.set('auth.token', body.data.token)
|
||||
}
|
||||
// 返回主体内容
|
||||
return Promise.resolve(body);
|
||||
}
|
29
common/cache.js
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
// 本地缓存封装
|
||||
export const TaCache = {
|
||||
|
||||
// 写入缓存数据,可配置有效时间(毫秒)
|
||||
set(name, value, expire = 0) {
|
||||
expire = expire > 0 ? Date.now() + expire : 0
|
||||
uni.setStorageSync(name, JSON.stringify([value, expire]))
|
||||
return value;
|
||||
},
|
||||
|
||||
/* 获取缓存数据 */
|
||||
get(name, defa = null) {
|
||||
try {
|
||||
let text = uni.getStorageSync(name)
|
||||
if (!text) return defa
|
||||
let data = JSON.parse(text)
|
||||
let isExpire = (data[1] || 0) > 0 && data[1] < Date.now()
|
||||
return isExpire ? (TaCache.del(name), defa) : data[0]
|
||||
} catch (e) {
|
||||
return defa
|
||||
}
|
||||
},
|
||||
|
||||
/* 删除缓存数据 */
|
||||
del(name) {
|
||||
uni.removeStorageSync(name)
|
||||
},
|
||||
}
|
458
common/free.css
Normal file
@ -0,0 +1,458 @@
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.status_bar {height: var(--status-bar-height); width: 100%;}
|
||||
/* scroll-view */
|
||||
.scroll-row{ width: 100%;white-space: nowrap; }
|
||||
.scroll-row-item{ display: inline-block!important; }
|
||||
/* #endif */
|
||||
/* 图标 */
|
||||
.iconfont{
|
||||
font-family:iconfont;
|
||||
}
|
||||
.view,.text{
|
||||
font-size:28rpx;
|
||||
line-height:1.8;
|
||||
color:#000000;
|
||||
}
|
||||
.img-in{font-size:0;}
|
||||
/* 宽度 */
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.w-100{ width: 100%; }
|
||||
.w-80{width: 80%;}
|
||||
.w-33{width: 33%;}
|
||||
/* #endif */
|
||||
.w-50{width: 50%;}
|
||||
.w-25{width: 25%;}
|
||||
.w-20{width: 20%;}
|
||||
.row {
|
||||
margin-right: -20rpx;
|
||||
margin-left: -20rpx;
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
.col-12 { width: 750rpx;}
|
||||
.col-11 { width: 687.5rpx; }
|
||||
.col-10 { width: 625rpx; }
|
||||
.col-9 { width: 562.5rpx; }
|
||||
.col-8 { width: 500rpx; }
|
||||
.col-7 { width: 437.5rpx; }
|
||||
.col-6 { width: 375rpx; }
|
||||
.col-5 { width: 312.5rpx;}
|
||||
.col-4 {width: 250rpx;}
|
||||
.col-3 {width: 187.5rpx;}
|
||||
.col-2 {width: 125rpx;}
|
||||
|
||||
|
||||
.col-1 {width: 62.5rpx;}
|
||||
|
||||
.col-offset-12 { margin-left: 750rpx;}
|
||||
.col-offset-11 { margin-left: 687.5rpx; }
|
||||
.col-offset-10 { margin-left: 625rpx; }
|
||||
.col-offset-9 { margin-left: 562.5rpx; }
|
||||
.col-offset-8 { margin-left: 500rpx; }
|
||||
.col-offset-7 { margin-left: 437.5rpx; }
|
||||
.col-offset-6 { margin-left: 375rpx; }
|
||||
.col-offset-5 { margin-left: 312.5rpx;}
|
||||
.col-offset-4 {margin-left: 250rpx;}
|
||||
.col-offset-3 {margin-left: 187.5rpx;}
|
||||
.col-offset-2 {margin-left: 125rpx;}
|
||||
.col-offset-1 {margin-left: 62.5rpx;}
|
||||
.col-offset-0 {margin-left: 0;}
|
||||
|
||||
/* flex 布局 */
|
||||
.flex{
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
display:flex!important;
|
||||
/* #endif */
|
||||
flex-direction:row;
|
||||
}
|
||||
.flex-row{ flex-direction:row!important; }
|
||||
.flex-column{ flex-direction:column!important; }
|
||||
.flex-row-reverse{ flex-direction:row-reverse!important; }
|
||||
.flex-column-reverse{ flex-direction:column-reverse!important; }
|
||||
.flex-wrap{ flex-wrap:wrap;}
|
||||
.flex-nowrap{ flex-wrap:nowrap;}
|
||||
.justify-start{justify-content:flex-start;}
|
||||
.justify-end{justify-content:flex-end;}
|
||||
.justify-between{justify-content:space-between;}
|
||||
.justify-center{justify-content:center;}
|
||||
.align-center{ align-items: center; }
|
||||
.align-stretch{ align-items: stretch; }
|
||||
.align-start{ align-items: flex-start; }
|
||||
.align-end{ align-items: flex-end; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.content-start {align-content: flex-start;}
|
||||
.content-end {align-content: flex-end;}
|
||||
.content-center {align-content: center;}
|
||||
.content-between {align-content: space-between;}
|
||||
.content-around {align-content: space-around;}
|
||||
.content-stretch {align-content: stretch;}
|
||||
/* #endif */
|
||||
.flex-1{ flex: 1; }
|
||||
.flex-2{ flex: 2; }
|
||||
.flex-3{ flex: 3; }
|
||||
.flex-4{ flex: 4; }
|
||||
.flex-5{ flex: 5; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.flex-shrink{ flex-shrink: 0; }
|
||||
/* #endif */
|
||||
|
||||
.containerx {
|
||||
padding-right: 20rpx;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
/* -- 内外边距 -- */
|
||||
.m-0 { margin: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.m-auto{ margin: auto; }
|
||||
/* #endif */
|
||||
.m-1 { margin: 10rpx; }
|
||||
.m-2 { margin: 20rpx; }
|
||||
.m-3 { margin: 30rpx; }
|
||||
.m-4 { margin: 40rpx; }
|
||||
.m-5 { margin: 50rpx; }
|
||||
.mt-0 { margin-top: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.mt-auto { margin-top: auto; }
|
||||
/* #endif */
|
||||
.mt-1 { margin-top: 10rpx; }
|
||||
.mt-2 { margin-top: 20rpx; }
|
||||
.mt-3 { margin-top: 30rpx; }
|
||||
.mt-4 { margin-top: 40rpx; }
|
||||
.mt-5 { margin-top: 50rpx; }
|
||||
.mb-0 { margin-bottom: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.mb-auto { margin-bottom: auto; }
|
||||
/* #endif */
|
||||
.mb-1 { margin-bottom: 10rpx; }
|
||||
.mb-2 { margin-bottom: 20rpx; }
|
||||
.mb-3 { margin-bottom: 30rpx; }
|
||||
.mb-4 { margin-bottom: 40rpx; }
|
||||
.mb-5 { margin-bottom: 50rpx; }
|
||||
.mb-6 { margin-bottom: 60rpx; }
|
||||
.mb-7 { margin-bottom: 70rpx; }
|
||||
.ml-0 { margin-left: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.ml-auto { margin-left: auto; }
|
||||
/* #endif */
|
||||
.ml-1 { margin-left: 10rpx; }
|
||||
.ml-2 { margin-left: 20rpx; }
|
||||
.ml-3 { margin-left: 30rpx; }
|
||||
.ml-4 { margin-left: 40rpx; }
|
||||
.ml-5 { margin-left: 50rpx; }
|
||||
.mr-0 { margin-right: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.mr-auto { margin-right: auto; }
|
||||
/* #endif */
|
||||
.mr-1 { margin-right: 10rpx; }
|
||||
.mr-2 { margin-right: 20rpx; }
|
||||
.mr-3 { margin-right: 30rpx; }
|
||||
.mr-4 { margin-right: 40rpx; }
|
||||
.mr-5 { margin-right: 50rpx; }
|
||||
.my-0 { margin-top: 0; margin-bottom: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.my-auto { margin-top: auto; margin-bottom: auto; }
|
||||
/* #endif */
|
||||
.my-1 { margin-top: 10rpx; margin-bottom: 10rpx; }
|
||||
.my-2 { margin-top: 20rpx; margin-bottom: 20rpx; }
|
||||
.my-3 { margin-top: 30rpx; margin-bottom: 30rpx; }
|
||||
.my-4 { margin-top: 40rpx; margin-bottom: 40rpx; }
|
||||
.my-5 { margin-top: 50rpx; margin-bottom: 50rpx; }
|
||||
.mx-0 { margin-left: 0; margin-right: 0; }
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.mx-auto { margin-left: auto; margin-right: auto; }
|
||||
/* #endif */
|
||||
.mx-1 { margin-left: 10rpx; margin-right: 10rpx;}
|
||||
.mx-2 { margin-left: 20rpx; margin-right: 20rpx;}
|
||||
.mx-3 { margin-left: 30rpx; margin-right: 30rpx;}
|
||||
.mx-4 { margin-left: 40rpx; margin-right: 40rpx;}
|
||||
.mx-5 { margin-left: 50rpx; margin-right: 50rpx;}
|
||||
|
||||
.p-0 { padding: 0; }
|
||||
.p { padding: 5rpx; }
|
||||
.p-1 { padding: 10rpx; }
|
||||
.p-2 { padding: 20rpx; }
|
||||
.p-3 { padding: 30rpx; }
|
||||
.p-4 { padding: 40rpx; }
|
||||
.p-5 { padding: 50rpx; }
|
||||
.pt-0 { padding-top: 0; }
|
||||
.pt { padding-top: 5rpx; }
|
||||
.pt-1 { padding-top: 10rpx; }
|
||||
.pt-2 { padding-top: 20rpx; }
|
||||
.pt-3 { padding-top: 30rpx; }
|
||||
.pt-4 { padding-top: 40rpx; }
|
||||
.pt-5 { padding-top: 50rpx; }
|
||||
.pb-0 { padding-bottom: 0; }
|
||||
.pb-1 { padding-bottom: 10rpx; }
|
||||
.pb { padding-bottom: 5rpx; }
|
||||
.pb-2 { padding-bottom: 20rpx; }
|
||||
.pb-3 { padding-bottom: 30rpx; }
|
||||
.pb-4 { padding-bottom: 40rpx; }
|
||||
.pb-5 { padding-bottom: 50rpx; }
|
||||
.pl-0 { padding-left: 0; }
|
||||
.pl { padding-left: 5rpx; }
|
||||
.pl-1 { padding-left: 10rpx; }
|
||||
.pl-2 { padding-left: 20rpx; }
|
||||
.pl-3 { padding-left: 30rpx; }
|
||||
.pl-4 { padding-left: 40rpx; }
|
||||
.pl-5 { padding-left: 50rpx; }
|
||||
.pl-9 { padding-left: 90rpx; }
|
||||
.pr-0 { padding-right: 0; }
|
||||
.pr { padding-right: 5rpx; }
|
||||
.pr-1 { padding-right: 10rpx; }
|
||||
.pr-2 { padding-right: 20rpx; }
|
||||
.pr-3 { padding-right: 30rpx; }
|
||||
.pr-4 { padding-right: 40rpx; }
|
||||
.pr-5 { padding-right: 50rpx; }
|
||||
.py-0 { padding-top: 0; padding-bottom: 0; }
|
||||
.py { padding-top: 5rpx; padding-bottom: 5rpx; }
|
||||
.py-1 { padding-top: 10rpx; padding-bottom: 10rpx; }
|
||||
.py-2 { padding-top: 20rpx; padding-bottom: 20rpx; }
|
||||
.py-25{padding-top: 25rpx; padding-bottom: 25rpx;}
|
||||
.py-3 { padding-top: 30rpx; padding-bottom: 30rpx; }
|
||||
.py-4 { padding-top: 40rpx; padding-bottom: 40rpx; }
|
||||
.py-5 { padding-top: 50rpx; padding-bottom: 50rpx; }
|
||||
.px-0 { padding-left: 0; padding-right: 0; }
|
||||
.px-1 { padding-left: 10rpx; padding-right: 10rpx;}
|
||||
.px { padding-left: 5rpx; padding-right: 5rpx;}
|
||||
.px-2 { padding-left: 20rpx; padding-right: 20rpx;}
|
||||
.px-3 { padding-left: 30rpx; padding-right: 30rpx;}
|
||||
.px-4 { padding-left: 40rpx; padding-right: 40rpx;}
|
||||
.px-5 { padding-left: 50rpx; padding-right: 50rpx;}
|
||||
|
||||
.font16{font-size: 16rpx!important;}
|
||||
.font18{font-size: 18rpx!important;}
|
||||
.font20{font-size: 20rpx!important;}
|
||||
.font22{font-size: 22rpx!important;}
|
||||
.font24{font-size: 24rpx!important;}
|
||||
.font26{font-size: 26rpx!important;}
|
||||
.font28{font-size: 28rpx!important;}
|
||||
.font30{font-size: 30rpx!important;}
|
||||
.font32{font-size: 32rpx!important;}
|
||||
.font34{font-size: 34rpx!important;}
|
||||
.font36{font-size: 36rpx!important;}
|
||||
.font38{font-size: 38rpx!important;}
|
||||
.font40{font-size: 40rpx!important;}
|
||||
.font50{font-size: 50rpx!important;}
|
||||
.font60{font-size: 60rpx!important;}
|
||||
/* 文字缩进 */
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.text-indent{text-indent:2;}
|
||||
.line15{line-height: 1.5;}
|
||||
.line2{line-height: 1.8;}
|
||||
/* #endif */
|
||||
/* 文字划线 */
|
||||
.text-through{text-decoration:line-through;}
|
||||
/* 文字对齐 */
|
||||
.text-left { text-align: left;}
|
||||
.text-right { text-align: right;}
|
||||
.text-center { text-align: center;}
|
||||
/* 文字换行溢出处理 */
|
||||
.text-ellipsis {
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
/* #endif */
|
||||
/* #ifdef APP-PLUS-NVUE */
|
||||
lines: 1;
|
||||
/* #endif */
|
||||
}
|
||||
.text-ellipsis-1 {
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
text-overflow: -o-ellipsis-lastline;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
|
||||
.text-ellipsis-2 {
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
text-overflow: -o-ellipsis-lastline;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
/* #endif */}
|
||||
/* 文字粗细和斜体 */
|
||||
.font-weight-light {font-weight: 300;} /*细*/
|
||||
.font-weight-lighter {font-weight: 100;}/*更细*/
|
||||
.font-weight-normal { font-weight: 400;} /*正常*/
|
||||
.font-weight-bold { font-weight: 700;} /*粗*/
|
||||
.font-weight-bolder { font-weight: bold;} /*更粗*/
|
||||
.font-italic { font-style: italic;} /*斜体*/
|
||||
/* 文字颜色 */
|
||||
.text-white {color: #ffffff;}
|
||||
.text-primary {color: #2979ff;}
|
||||
.text-hover-primary { color: #94bcff;}
|
||||
.text-secondary {color: #6c757d;}
|
||||
.text-hover-secondary { color: #494f54;}
|
||||
.text-success {color: #18bc37;}
|
||||
.text-hover-success{color: #8cde9b;}
|
||||
.text-info { color: #8f939c;}
|
||||
.text-hover-info {color: #c7c9ce;}
|
||||
.text-warning {color: #ffc107;}
|
||||
.text-hover-warning { color: #f9d39f;}
|
||||
.text-danger { color: #e43d33 ;}
|
||||
.text-hover-danger { color: #f29e99;}
|
||||
.text-light { color: #e9e9eb;}
|
||||
.text-hover-light { color: #cbd3da;}
|
||||
.text-dark { color: #343a40;}
|
||||
.text-hover-dark{ color: #8f939c;}
|
||||
.text-body { color: #000000;}
|
||||
.text-muted { color: #979797;}
|
||||
/* 浅灰色 */
|
||||
.text-light-muted { color: #A9A5A0;}
|
||||
.text-light-black { color: rgba(0, 0, 0, 0.5);}
|
||||
.text-light-white { color: rgba(255, 255, 255, 0.5);}
|
||||
|
||||
/* 背景颜色 */
|
||||
|
||||
.bg-primary { background-color: #2979ff;}
|
||||
.bg-hover-primary:hover{ background-color: #94bcff;}
|
||||
.bg-secondary { background-color: #6c757d;}
|
||||
.bg-hover-secondary:hover{ background-color: #545b62;}
|
||||
.bg-success { background-color: #18bc37;}
|
||||
.bg-hover-success { background-color: #8cde9b;}
|
||||
.bg-info { background-color: #8f939c;}
|
||||
.bg-hover-info { background-color: #c7c9ce;}
|
||||
.bg-warning { background-color: #f3a73f;}
|
||||
.bg-hover-warning { background-color: #f9d39f;}
|
||||
.bg-danger { background-color: #e43d33 ;}
|
||||
.bg-hover-danger{ background-color: #f29e99;}
|
||||
.bg-light { background-color: #e9e9eb;}
|
||||
.bg-hover-light{ background-color: #f1f1f1;}
|
||||
.bg-dark { background-color: #333333;}
|
||||
.bg-hover-dark { background-color: #1d2124;}
|
||||
.bg-white { background-color: #ffffff;}
|
||||
.bg-transparent { background-color: transparent;}
|
||||
/* 边框 */
|
||||
.border { border-width: 1rpx;border-style: solid;border-color: #dee2e6;}
|
||||
.border-top {
|
||||
border-top-width: 1rpx;
|
||||
border-top-style: solid;
|
||||
border-top-color: #dee2e6;
|
||||
}
|
||||
.border-right {
|
||||
border-right-width: 1rpx;
|
||||
border-right-style: solid;
|
||||
border-right-color: #dee2e6;
|
||||
}
|
||||
.border-bottom {
|
||||
border-bottom-width: 1rpx;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #dee2e6;
|
||||
}
|
||||
.border-left {
|
||||
border-left-width: 1rpx;
|
||||
border-left-style: solid;
|
||||
border-left-color: #dee2e6;
|
||||
}
|
||||
.border-dotted-bottom {
|
||||
border-bottom-width: 1rpx;
|
||||
border-bottom-style: dotted;
|
||||
border-bottom-color: #dee2e6;
|
||||
}
|
||||
.border-0 { border-width: 0!important;}
|
||||
.border-top-0 { border-top-width: 0!important;}
|
||||
.border-right-0 {border-right-width: 0!important;}
|
||||
.border-bottom-0 {border-bottom-width: 0!important;}
|
||||
.border-left-0 {border-left-width: 0!important;}
|
||||
.border-primary { border-color: #2979ff;}
|
||||
.border-secondary {border-color: #6c757d;}
|
||||
.border-light-secondary {border-color: #E9E8E5;}
|
||||
.border-success {border-color: #18bc37;}
|
||||
.border-info {border-color: #8f939c;}
|
||||
.border-warning {border-color: #f3a73f;}
|
||||
.border-danger {border-color:#e43d33 ;}
|
||||
.border-light {border-color: #e9e9eb;}
|
||||
.border-dark {border-color: #343a40;}
|
||||
.border-white {border-color: #FFFFFF;}
|
||||
|
||||
|
||||
/* 圆角 */
|
||||
.rounded { border-radius: 8rpx;}
|
||||
.rounded-lg { border-radius: 14rpx;}
|
||||
.rounded-top {
|
||||
border-top-left-radius: 8rpx;
|
||||
border-top-right-radius: 8rpx;
|
||||
}
|
||||
.rounded-top-lg {
|
||||
border-top-left-radius: 14rpx;
|
||||
border-top-right-radius: 14rpx;
|
||||
}
|
||||
.rounded-right {
|
||||
border-top-right-radius: 8rpx;
|
||||
border-bottom-right-radius: 8rpx;
|
||||
}
|
||||
.rounded-bottom {
|
||||
border-bottom-right-radius: 8rpx;
|
||||
border-bottom-left-radius: 8rpx;
|
||||
}
|
||||
.rounded-bottom-lg {
|
||||
border-bottom-right-radius: 14rpx;
|
||||
border-bottom-left-radius: 14rpx;
|
||||
}
|
||||
.rounded-left {
|
||||
border-top-left-radius: 8rpx;
|
||||
border-bottom-left-radius: 8rpx;
|
||||
}
|
||||
.rounded-circle { border-radius: 100rpx;}
|
||||
.rounded-circle-left { border-radius: 100rpx 0 0 100rpx;}
|
||||
.rounded-circle-right { border-radius:0 100rpx 100rpx 0 ;}
|
||||
.rounded-0 { border-radius: 0;}
|
||||
/* 显示 */
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.d-none{ display: none; }
|
||||
.d-inline-block{ display: inline-block; }
|
||||
.d-block{ display: block; }
|
||||
/* #endif */
|
||||
/* 内容溢出 */
|
||||
.overflow-hidden { overflow: hidden;}
|
||||
/* 定位 */
|
||||
.position-relative { position: relative;}
|
||||
.position-absolute { position: absolute;}
|
||||
.position-fixed { position: fixed;}
|
||||
.position-sticky{position: sticky;top: 0; z-index: 1000;}
|
||||
/* 定位 - 固定顶部 */
|
||||
.fixed-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
z-index: 1030;
|
||||
}
|
||||
/* 定位 - 固定底部 */
|
||||
.fixed-bottom {
|
||||
position: fixed;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
.top-0 { top: 0; }
|
||||
.left-0 { left: 0; }
|
||||
.right-0 { right: 0; }
|
||||
.bottom-0 { bottom: 0; }
|
||||
|
||||
/* 阴影 */
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
.shadow { box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.15);}
|
||||
.shadow-lg { box-shadow: 0rpx 40rpx 100rpx 0rpx rgba(0, 0, 0, 0.175);}
|
||||
.shadow-none { box-shadow: none !important;}
|
||||
/* #endif */
|
||||
.cu-tabbar-height {height: 110upx;}
|
||||
.cny::before {content: "¥";font-size: 60%;margin-right: 10rpx;}
|
||||
.cny_jf::before {content: "积分";font-size: 60%;margin-right: 10rpx;}
|
||||
.opacity9{opacity: 0.9;}
|
352
common/html-parser.js
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* HTML5 Parser By Sam Blowes
|
||||
*
|
||||
* Designed for HTML5 documents
|
||||
*
|
||||
* Original code by John Resig (ejohn.org)
|
||||
* http://ejohn.org/blog/pure-javascript-html-parser/
|
||||
* Original code by Erik Arvidsson, Mozilla Public License
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* License
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* This code is triple licensed using Apache Software License 2.0,
|
||||
* Mozilla Public License or GNU Public License
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Simple HTML Parser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Erik Arvidsson.
|
||||
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
|
||||
* Reserved.
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Usage
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* // Use like so:
|
||||
* HTMLParser(htmlString, {
|
||||
* start: function(tag, attrs, unary) {},
|
||||
* end: function(tag) {},
|
||||
* chars: function(text) {},
|
||||
* comment: function(text) {}
|
||||
* });
|
||||
*
|
||||
* // or to get an XML string:
|
||||
* HTMLtoXML(htmlString);
|
||||
*
|
||||
* // or to get an XML DOM Document
|
||||
* HTMLtoDOM(htmlString);
|
||||
*
|
||||
* // or to inject into an existing document/DOM node
|
||||
* HTMLtoDOM(htmlString, document);
|
||||
* HTMLtoDOM(htmlString, document.body);
|
||||
*
|
||||
*/
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
|
||||
|
||||
var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
|
||||
// fixed by xxx 将 ins 标签从块级名单中移除
|
||||
|
||||
var block = makeMap('a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'); // Inline Elements - HTML 5
|
||||
|
||||
var inline = makeMap('abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'); // Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
|
||||
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
|
||||
|
||||
var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
|
||||
|
||||
var special = makeMap('script,style');
|
||||
function HTMLParser(html, handler) {
|
||||
var index;
|
||||
var chars;
|
||||
var match;
|
||||
var stack = [];
|
||||
var last = html;
|
||||
|
||||
stack.last = function () {
|
||||
return this[this.length - 1];
|
||||
};
|
||||
|
||||
while (html) {
|
||||
chars = true; // Make sure we're not in a script or style element
|
||||
|
||||
if (!stack.last() || !special[stack.last()]) {
|
||||
// Comment
|
||||
if (html.indexOf('<!--') == 0) {
|
||||
index = html.indexOf('-->');
|
||||
|
||||
if (index >= 0) {
|
||||
if (handler.comment) {
|
||||
handler.comment(html.substring(4, index));
|
||||
}
|
||||
|
||||
html = html.substring(index + 3);
|
||||
chars = false;
|
||||
} // end tag
|
||||
|
||||
} else if (html.indexOf('</') == 0) {
|
||||
match = html.match(endTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(endTag, parseEndTag);
|
||||
chars = false;
|
||||
} // start tag
|
||||
|
||||
} else if (html.indexOf('<') == 0) {
|
||||
match = html.match(startTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(startTag, parseStartTag);
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
index = html.indexOf('<');
|
||||
var text = index < 0 ? html : html.substring(0, index);
|
||||
html = index < 0 ? '' : html.substring(index);
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function (all, text) {
|
||||
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
|
||||
if (html == last) {
|
||||
throw 'Parse Error: ' + html;
|
||||
}
|
||||
|
||||
last = html;
|
||||
} // Clean up any remaining tags
|
||||
|
||||
|
||||
parseEndTag();
|
||||
|
||||
function parseStartTag(tag, tagName, rest, unary) {
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
if (block[tagName]) {
|
||||
while (stack.last() && inline[stack.last()]) {
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
}
|
||||
|
||||
if (closeSelf[tagName] && stack.last() == tagName) {
|
||||
parseEndTag('', tagName);
|
||||
}
|
||||
|
||||
unary = empty[tagName] || !!unary;
|
||||
|
||||
if (!unary) {
|
||||
stack.push(tagName);
|
||||
}
|
||||
|
||||
if (handler.start) {
|
||||
var attrs = [];
|
||||
rest.replace(attr, function (match, name) {
|
||||
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[name] ? name : '';
|
||||
attrs.push({
|
||||
name: name,
|
||||
value: value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
if (handler.start) {
|
||||
handler.start(tagName, attrs, unary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag(tag, tagName) {
|
||||
// If no tag name is provided, clean shop
|
||||
if (!tagName) {
|
||||
var pos = 0;
|
||||
} // Find the closest opened tag of the same type
|
||||
else {
|
||||
for (var pos = stack.length - 1; pos >= 0; pos--) {
|
||||
if (stack[pos] == tagName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (var i = stack.length - 1; i >= pos; i--) {
|
||||
if (handler.end) {
|
||||
handler.end(stack[i]);
|
||||
}
|
||||
} // Remove the open elements from the stack
|
||||
|
||||
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeMap(str) {
|
||||
var obj = {};
|
||||
var items = str.split(',');
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
obj[items[i]] = true;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function removeDOCTYPE(html) {
|
||||
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
|
||||
}
|
||||
|
||||
function parseAttrs(attrs) {
|
||||
return attrs.reduce(function (pre, attr) {
|
||||
var value = attr.value;
|
||||
var name = attr.name;
|
||||
|
||||
if (pre[name]) {
|
||||
pre[name] = pre[name] + " " + value;
|
||||
} else {
|
||||
pre[name] = value;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function parseHtml(html) {
|
||||
html = removeDOCTYPE(html);
|
||||
var stacks = [];
|
||||
var results = {
|
||||
node: 'root',
|
||||
children: []
|
||||
};
|
||||
HTMLParser(html, {
|
||||
start: function start(tag, attrs, unary) {
|
||||
var node = {
|
||||
name: tag
|
||||
};
|
||||
|
||||
if (attrs.length !== 0) {
|
||||
node.attrs = parseAttrs(attrs);
|
||||
}
|
||||
|
||||
if (unary) {
|
||||
var parent = stacks[0] || results;
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
stacks.unshift(node);
|
||||
}
|
||||
},
|
||||
end: function end(tag) {
|
||||
var node = stacks.shift();
|
||||
if (node.name !== tag) console.error('invalid state: mismatch end tag');
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
chars: function chars(text) {
|
||||
var node = {
|
||||
type: 'text',
|
||||
text: text
|
||||
};
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
comment: function comment(text) {
|
||||
var node = {
|
||||
node: 'comment',
|
||||
text: text
|
||||
};
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
});
|
||||
return results.children;
|
||||
}
|
||||
|
||||
export default parseHtml;
|
76
common/image.js
Normal file
@ -0,0 +1,76 @@
|
||||
// 读取图片 Base64 内容
|
||||
export function TaImageToBase64(file, maxw = 500) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (uni.compressImage) {
|
||||
uni.compressImage({
|
||||
src: file,
|
||||
quality: 80,
|
||||
width: maxw + "px",
|
||||
fail: err => reject(err),
|
||||
success: res =>
|
||||
readFileAsBase64(res.tempFilePath)
|
||||
.then(resolve)
|
||||
.catch(reject)
|
||||
})
|
||||
} else {
|
||||
let img = new Image();
|
||||
(img.crossOrigin = "Anonymous"),
|
||||
(img.onload = () => {
|
||||
let c = document.createElement("canvas")
|
||||
let w = img.naturalWidth,
|
||||
h = img.naturalHeight;
|
||||
(c.width = Math.min(maxw, w)), (c.height = c.width * (h / w))
|
||||
// @ts-ignore
|
||||
c.getContext("2d").drawImage(img, 0, 0, c.width, c.height)
|
||||
resolve(c.toDataURL("image/jpeg", 0.8))
|
||||
}),
|
||||
(img.src = file),
|
||||
(img.onerror = () => reject(new Error("Failed to load image")))
|
||||
}
|
||||
})
|
||||
|
||||
// 读取文件为 base64 格式
|
||||
function readFileAsBase64(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let rd = new plus.io.FileReader()
|
||||
rd.onerror = e => reject(e)
|
||||
rd.onloadend = v => resolve(v.target.result)
|
||||
// @ts-ignore
|
||||
rd.readAsDataURL(plus.io.convertLocalFileSystemURL(file))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 下载图片到本地
|
||||
export function TaImageDownload(imgUrl, name = "") {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef H5
|
||||
const link = document.createElement("a")
|
||||
link.href = imgUrl
|
||||
link.download =
|
||||
name ||
|
||||
Math.random()
|
||||
.toString()
|
||||
.replace("0.", "img") + `.png`
|
||||
link.style.display = "none"
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
resolve(true)
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.downloadFile({
|
||||
url: imgUrl,
|
||||
success: ret => {
|
||||
if (ret.statusCode === 200)
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: ret.tempFilePath,
|
||||
fail: err => TaToast.error("保存失败!", err).then(reject),
|
||||
success: () => TaToast.success("保存成功!").then(resolve)
|
||||
})
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
}
|
1122
common/qqmap-wx-jssdk.js
Normal file
56
common/toast.js
Normal file
@ -0,0 +1,56 @@
|
||||
// Toast 默认延时关闭时间
|
||||
const _time_ = 2000;
|
||||
|
||||
// Toast 消息处理,最多显示七个汉字
|
||||
export const TaToast = {
|
||||
|
||||
// 隐藏消息显示
|
||||
hide() {
|
||||
uni.hideToast()
|
||||
},
|
||||
|
||||
// 通用消息显示
|
||||
show(info, type = 'none', mask = true, time = _time_) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, time)
|
||||
uni.showToast({
|
||||
mask: mask || false,
|
||||
icon: type || 'none',
|
||||
title: info,
|
||||
duration: time
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 异常消息显示
|
||||
error(info, mask = true, time = _time_) {
|
||||
return this.show(info, 'error', mask, time)
|
||||
},
|
||||
|
||||
// 成功消息显示
|
||||
success(info, mask = true, time = _time_) {
|
||||
return this.show(info, 'success', mask, time)
|
||||
},
|
||||
|
||||
// 确认消息框架
|
||||
confirm(content, title = '操作确认?') {
|
||||
return new Promise((resolve, reject) => uni.showModal({
|
||||
title,
|
||||
content,
|
||||
success: (res) => (res.cancel && reject(), res.confirm && resolve(res))
|
||||
}))
|
||||
},
|
||||
|
||||
// 显示加载消息
|
||||
loading(info = '', mask = true) {
|
||||
uni.showLoading({
|
||||
mask: mask,
|
||||
title: info
|
||||
})
|
||||
},
|
||||
|
||||
// 隐藏加载消息
|
||||
loadhide() {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}
|
89
common/util.js
Normal file
@ -0,0 +1,89 @@
|
||||
function friendlyDate(timestamp) {
|
||||
var formats = {
|
||||
'year': '%n% 年前',
|
||||
'month': '%n% 月前',
|
||||
'day': '%n% 天前',
|
||||
'hour': '%n% 小时前',
|
||||
'minute': '%n% 分钟前',
|
||||
'second': '%n% 秒前',
|
||||
};
|
||||
|
||||
var now = Date.now();
|
||||
var seconds = Math.floor((now - timestamp) / 1000);
|
||||
var minutes = Math.floor(seconds / 60);
|
||||
var hours = Math.floor(minutes / 60);
|
||||
var days = Math.floor(hours / 24);
|
||||
var months = Math.floor(days / 30);
|
||||
var years = Math.floor(months / 12);
|
||||
|
||||
var diffType = '';
|
||||
var diffValue = 0;
|
||||
if (years > 0) {
|
||||
diffType = 'year';
|
||||
diffValue = years;
|
||||
} else {
|
||||
if (months > 0) {
|
||||
diffType = 'month';
|
||||
diffValue = months;
|
||||
} else {
|
||||
if (days > 0) {
|
||||
diffType = 'day';
|
||||
diffValue = days;
|
||||
} else {
|
||||
if (hours > 0) {
|
||||
diffType = 'hour';
|
||||
diffValue = hours;
|
||||
} else {
|
||||
if (minutes > 0) {
|
||||
diffType = 'minute';
|
||||
diffValue = minutes;
|
||||
} else {
|
||||
diffType = 'second';
|
||||
diffValue = seconds === 0 ? (seconds = 1) : seconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return formats[diffType].replace('%n%', diffValue);
|
||||
}
|
||||
|
||||
function objectHasKey(o, k) {
|
||||
return Object.keys(o).some((v) => v.toLowerCase() === k.toLowerCase())
|
||||
}
|
||||
|
||||
|
||||
// 下载图片到本地
|
||||
function TaImageDownload(imgUrl, name = '') {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
// #ifdef H5
|
||||
const link = document.createElement('a')
|
||||
link.href = imgUrl
|
||||
link.download = name || (Math.random().toString().replace('0.', 'img') + `.png`)
|
||||
link.style.display = 'none'
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
resolve(true)
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
uni.downloadFile({
|
||||
url: imgUrl, success: (ret) => {
|
||||
if (ret.statusCode === 200) uni.saveImageToPhotosAlbum({
|
||||
filePath: ret.tempFilePath,
|
||||
fail: (err) => TaToast.error('保存失败!', err).then(reject),
|
||||
success: () => TaToast.success('保存成功!').then(resolve),
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
|
||||
export {
|
||||
TaImageDownload,
|
||||
friendlyDate,
|
||||
objectHasKey
|
||||
}
|
38
components/i-account-list/i-account-list.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="flex align-center justify-between border-top py-3">
|
||||
<view class="flex-1 text-center" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<view class="font32">100</view>
|
||||
<view class="text-muted font24 mt-1">优惠券</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-account-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
console.log("链接")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
56
components/i-account/i-account.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="flex align-center py-3 " >
|
||||
<view class="flex-1 flex align-center">
|
||||
<image src="/static/avatar.png" style="width: 120rpx;height: 120rpx;"
|
||||
class="rounded-circle mr-2"></image>
|
||||
<view class="flex-1">
|
||||
<view class="font34">小王</view>
|
||||
<view class="font28 mt-2 text-muted">187****0002</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-icons type="right" size="18" color="#333333" ></uni-icons>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "i-account",
|
||||
props: {
|
||||
avatar: {
|
||||
type: String,
|
||||
default () {
|
||||
return '/static/avatar.png';
|
||||
},
|
||||
},
|
||||
nickname: {
|
||||
type: String,
|
||||
default () {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
userid: {
|
||||
type: String,
|
||||
default () {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toShow() {
|
||||
console.log('链接')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
64
components/i-address-list/i-address-list.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="bg-white rounded-lg mb-2 p-3" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<view class="border-dotted-bottom pb-3">
|
||||
<view class="flex align-center font32">
|
||||
<text>{{item.user_name}}</text>
|
||||
<text class="ml-3">{{item.user_phone}}</text>
|
||||
</view>
|
||||
<view class="mt-1 font30 line15">{{item.region_prov}}{{item.region_city}}{{item.region_area}}{{item.region_addr}}</view>
|
||||
</view>
|
||||
<view class="flex align-center justify-between pt-3" @click.stop>
|
||||
<view class="flex align-center justify-end">
|
||||
<uni-icons @click="toEdit(item)" type="compose" size="20" color="#999999" class="mr-3"></uni-icons>
|
||||
<uni-icons @click="toDelete(item)" type="trash" size="20" color="#999999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-address-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
this.$emit('click',item)
|
||||
},
|
||||
toEdit(item) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/address_edit?id="+item.id
|
||||
})
|
||||
},
|
||||
toDelete(item) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
console.log('用户点击确定');
|
||||
this.$emit('delete',item)
|
||||
} else if (res.cancel) {
|
||||
console.log('用户点击取消');
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
console.log('取消删除');
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
49
components/i-cart-list/i-cart-list.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="bg-white mt-2 px-2 py-3 flex align-center" v-for="(item,index) in resdata" :key="index">
|
||||
<uni-icons type="circle" size="24" color="#cccccc"></uni-icons>
|
||||
<view class="flex-1 ml-2 flex align-start">
|
||||
<image src="/static/pro1.jpg" style="width: 150rpx;height: 150rpx;" class="flex-shrink mr-2 rounded"></image>
|
||||
<view class="flex-1">
|
||||
<view class="flex align-center">
|
||||
<view class="text-ellipsis-1 font32 flex-1 mr-2">现货供应抗震盘螺大量批发</view>
|
||||
<uni-icons type="trash" size="20" color="#999999"></uni-icons>
|
||||
</view>
|
||||
<view class="flex align-center mt-2 font28">
|
||||
<text class="text-muted flex-shrink">类型:</text>
|
||||
<view class="flex-1 text-ellipsis-1">螺纹钢-20*20-GB2301-马场空</view>
|
||||
</view>
|
||||
<view class="flex align-center justify-between mt-2">
|
||||
<view class="text-danger">
|
||||
<text class="cny">99.9</text>
|
||||
</view>
|
||||
<uni-number-box />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-cart-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
49
components/i-list-top/i-list-top.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-row :gutter="30">
|
||||
<uni-col :span="12" v-for="(item,index) in resdata" :key="index" >
|
||||
<view class="bg-white mt-3 rounded-lg overflow-hidden pb-3" @click="toShow(item.code)">
|
||||
<image :src="item.cover" class="rounded-top-lg" style="width: 345rpx; height: 345rpx;" mode="aspectFill"></image>
|
||||
|
||||
<view class="font28 text-ellipsis-1 px-2 mt-2">{{item.name}}</view>
|
||||
<view class="mt-1 flex align-end px-2">
|
||||
<view class="text-danger">
|
||||
<text class="cny_jf">{{item.price_selling}}</text>
|
||||
</view>
|
||||
<view class="font24 text-through cny ml-2 text-muted">{{item.price_market}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-list-top",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(id){
|
||||
uni.navigateTo({
|
||||
url:'/pages/points-mall/detail?code='+id
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
39
components/i-loading/i-loading.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view class="fullloading flex align-center justify-center">
|
||||
<view class="text-center">
|
||||
<view class="flex align-center justify-center">
|
||||
<view class="animate1 mr-1">
|
||||
<uni-icons type="smallcircle-filled" size="14" color="#999"></uni-icons>
|
||||
</view>
|
||||
<view class="animate2 mr-1">
|
||||
<uni-icons type="smallcircle-filled" size="14" color="#999"></uni-icons>
|
||||
</view>
|
||||
<view class="animate3">
|
||||
<uni-icons type="smallcircle-filled" size="14" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="font28 mt-1 text-muted text-center">加载中,请稍候</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-loading",
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fullloading{position: fixed;left: 0;top: 0;width: 100%;height: 100%;background-color: #FFFFFF;z-index: 99999;right: 0;bottom: 0;}
|
||||
@keyframes pageLoading1{0% {opacity:0.5; transform:scale(1);} 40% {opacity:1; transform:scale(1.3);} 60%{opacity:0.5; transform:scale(1);}}
|
||||
@keyframes pageLoading2{20% {opacity:0.5; transform:scale(1);} 60% {opacity:1; transform:scale(1.3);} 80% {opacity:0.5; transform:scale(1);}}
|
||||
@keyframes pageLoading3{40% {opacity:0.5; transform:scale(1);} 80% {opacity:1; transform:scale(1.3);} 100% {opacity:0.5; transform:scale(1);}}
|
||||
.animate1{animation:pageLoading1 1.2s infinite linear;}
|
||||
.animate2{animation:pageLoading2 1.2s infinite linear;}
|
||||
.animate3{animation:pageLoading3 1.2s infinite linear;}
|
||||
</style>
|
67
components/i-message-list/i-message-list.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 rounded-lg bg-white mt-2 position-relative" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<text class="font32 line15">{{item.title}}</text>
|
||||
<view class="font24 mt-2 text-ellipsis-2">
|
||||
{{item.content}}
|
||||
</view>
|
||||
<view class="flex align-center justify-between mt-2">
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="calendar" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">{{item.create_at}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="item.status == 0" class="badge-dot"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaPost } from '../../common/ajax';
|
||||
|
||||
export default {
|
||||
name:"i-message-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
console.log(this.resdata)
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
TaPost("/custom/api.auth.message/read", {id: item.id}).then((result) => {
|
||||
item.status = 1;
|
||||
})
|
||||
switch (item.type) {
|
||||
case "USER_SHARE":
|
||||
uni.navigateTo({
|
||||
url: '/pages/user-share/detail?id='+item.oid
|
||||
})
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.badge-dot {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
right: 16rpx;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
background-color: red;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
</style>
|
40
components/i-my-list/i-my-list.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="flex align-center justify-between py-3 active" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<view class="flex align-center flex-1">
|
||||
<image src="/static/tabbar/my.png" style="width: 40rpx;height: 40rpx;" class="mr-2 flex-shrink"></image>
|
||||
<view class="flex-1 font30">编辑资料</view>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#dddddd"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-my-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
console.log('链接')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.active{border-bottom: 1rpx solid #f1f1f1;}
|
||||
.active:last-child{border-bottom: 0rpx solid #f1f1f1;}
|
||||
</style>
|
44
components/i-nav-list/i-nav-list.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="flex align-center flex-wrap pb-3">
|
||||
<view class=" text-center pt-3" :class="column==5?'w-20':'w-25'" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<image src="/static/icon.jpg" style="width: 80rpx;height: 80rpx;" class="rounded-lg"></image>
|
||||
<view class="text-muted font24 mt-1 text-ellipsis-1">标题</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-nav-list",
|
||||
props:{
|
||||
column:{
|
||||
type:Number,
|
||||
default() {
|
||||
return 4;
|
||||
},
|
||||
},
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
this.$emit('click',item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
55
components/i-news-list/i-news-list.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 rounded-lg bg-white mt-2 flex flex-row" v-for="(item,index) in resdata" :key="index" @click="toShow(item)" style="gap: 20rpx;">
|
||||
<view class="flex-0" v-if="item.imgs.length > 0" style="flex-basis: 256rpx;">
|
||||
<image :src="item.imgs[0]" style="width:256rpx;height: 160rpx; border-radius: 16rpx;" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="flex-5 flex flex-column justify-between" style="height: 160rpx;">
|
||||
<view><text class="font32 line15">{{item.title}}</text></view>
|
||||
<view class="flex align-center justify-between mt-2">
|
||||
<view class="flex align-center">
|
||||
<text class="font24 text-muted">{{item.publish_at}}</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<text class="font24 text-muted">{{item.view_count}}人浏览</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-news-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
console.log(this.resdata)
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/news/detail?id='+item.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
54
components/i-nodata/i-nodata.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="flex align-center justify-center">
|
||||
<view class="text-center">
|
||||
<image :src="src" style="width: 300rpx;height: 248rpx;"></image>
|
||||
<view class="font32 text-center">{{title}}</view>
|
||||
<view class="mt-2 font28 text-muted text-center" v-if="subtitle">{{subtitle}}</view>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-nodata",
|
||||
props:{
|
||||
src:{
|
||||
type:String,
|
||||
default(){
|
||||
return '/static/zanwu.png'
|
||||
}
|
||||
},
|
||||
title:{
|
||||
type:String,
|
||||
default(){
|
||||
return '空空如也'
|
||||
}
|
||||
},
|
||||
subtitle:{
|
||||
type:String,
|
||||
default(){
|
||||
return null
|
||||
}
|
||||
},
|
||||
isBtn:{
|
||||
type:Boolean,
|
||||
default(){
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
toShow(){
|
||||
this.$emit('click')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
48
components/i-notice-list/i-notice-list.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<view class="flex align-center rounded-lg bg-white p-2">
|
||||
<view class="mr-2 border-right pr-2 flex-shrink border-light">
|
||||
<uni-icons type="notification" size="20" color="#e43d33"></uni-icons>
|
||||
</view>
|
||||
<swiper class="swiperNotice flex-1" :ndicator-dots="false"
|
||||
autoplay
|
||||
:interval="3000"
|
||||
:duration="1000"
|
||||
:vertical="true"
|
||||
:circular="true">
|
||||
<swiper-item v-for="(item,index) in resdata" :key="index" >
|
||||
<view class="font28 text-ellipsis-1" @tap="toNotice(item)">特别公告:禁止上传 任何 涉及 第三方版权资料</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<text class="font28 ml-2 text-muted" @click="toNews">更多</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default{
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
},
|
||||
// 计算属性
|
||||
|
||||
methods:{
|
||||
toNotice(item){
|
||||
this.$emit('showClick',item)
|
||||
},
|
||||
toNews(){
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.swiperNotice {
|
||||
height: 50rpx; line-height: 50rpx;
|
||||
}
|
||||
</style>
|
113
components/i-order-list/i-order-list.vue
Normal file
@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="bg-white p-3 rounded-lg mt-2 mx-2" v-for="(item,index) in resdata" :key="index">
|
||||
<view class="flex align-center justify-between pb-3 border-bottom">
|
||||
<view class="text-muted font28">{{item.create_time}}</view>
|
||||
<view class="text-danger font28" v-if="item.status == 0">已取消</view>
|
||||
<view class="text-danger font28" v-else-if="item.status <= 2">待支付</view>
|
||||
<view class="text-danger font28" v-else-if="item.status == 3">待验证</view>
|
||||
<view class="text-danger font28" v-else-if="item.status == 4">待发货</view>
|
||||
<view class="text-danger font28" v-else-if="item.status == 5">待收货</view>
|
||||
<view class="text-danger font28" v-else-if="item.status == 6">已收货</view>
|
||||
</view>
|
||||
<!-- 单个产品 -->
|
||||
<view class="py-3 flex align-start" @click="toShow(gitem)" v-for="(gitem, gindex) in item.items" :key="gindex">
|
||||
<image :src="gitem.gcover" style="width: 150rpx;height: 150rpx;" class="flex-shrink mr-2 rounded"></image>
|
||||
<view class="flex-1">
|
||||
<view class="text-ellipsis-1 font32">{{gitem.gname}}</view>
|
||||
<view class="flex align-center justify-between mt-2 ">
|
||||
<view class="text-danger">
|
||||
<text class="cny_jf">{{gitem.total_price_cost}}</text>
|
||||
</view>
|
||||
<view class="flex align-center justify-end font28">
|
||||
<text class="text-muted">数量:</text>
|
||||
<text>{{gitem.stock_sales}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 多个产品 -->
|
||||
<!-- <view class="flex align-center py-3" v-else @click="toShow(item)">
|
||||
<image src="/static/pro1.jpg" style="width: 150rpx;height: 150rpx;" class="flex-shrink mr-2 rounded"></image>
|
||||
<image src="/static/pro1.jpg" style="width: 150rpx;height: 150rpx;" class="flex-shrink mr-2 rounded"></image>
|
||||
<image src="/static/pro1.jpg" style="width: 150rpx;height: 150rpx;" class="flex-shrink mr-2 rounded"></image>
|
||||
</view> -->
|
||||
|
||||
<view class="flex align-center justify-end pb-3 border-bottom">
|
||||
<view class="flex align-center font30 mr-2">
|
||||
<text class="text-muted">共</text>
|
||||
<text class="mx-1">{{item.number_goods}}</text>
|
||||
<text class="text-muted">件商品</text>
|
||||
</view>
|
||||
<view class="flex align-center font28">
|
||||
<text class="text-muted">总消耗</text>
|
||||
<text class="ml-1 cny_jf text-danger">{{item.amount_total}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex align-center justify-end pt-3">
|
||||
<view class="bg-light text-muted font28 px-3 py-2 rounded-circle ml-2" v-if="item.status > 0 && item.status <= 2" @click="doCancel(item)">取消</view>
|
||||
<view class="bg-danger text-white font28 px-4 py-2 rounded-circle ml-2" v-if="item.status == 5" @click="doConfirm(item)">确认收货</view>
|
||||
<view class="bg-success text-white font28 px-4 py-2 rounded-circle ml-2" v-if="item.status > 0 && item.status <= 2" @click="toPay(item)">支付</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax';
|
||||
|
||||
export default {
|
||||
name:"i-order-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/order/orderDetail'
|
||||
})
|
||||
},
|
||||
toPay(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/points-mall/buy?order_no='+item.order_no
|
||||
})
|
||||
},
|
||||
doConfirm(item) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定收货吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.$emit("confirm", item.order_no)
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
doCancel(item) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定取消订单吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.$emit("cancel", item.order_no)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
39
components/i-search/i-search.vue
Normal file
@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="border rounded-lg overflow-hidden flex align-stretch">
|
||||
<input :placeholder="placeholder" v-model="value" class="flex-1 font30 py-2 px-3" />
|
||||
<view class=" font30 flex-shrink px-3 py-2 flex align-center border-left" @click="toSearch">
|
||||
<uni-icons type="search" size="16" color="#666666"></uni-icons>
|
||||
<text class="ml-1">搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-search",
|
||||
props:{
|
||||
placeholder:{
|
||||
type: String,
|
||||
default() {
|
||||
return null;
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value:null
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toSearch(){
|
||||
this.$emit('click',this.value)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
45
components/i-spread/i-spread.vue
Normal file
@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<view class="overflow-hidden position-relative" :class="[isShrink ? 'gui-transition-all' : '']" :style="{height:reHeight}">
|
||||
<view :style="{ paddingBottom: !isBtn && isShrink ? '80rpx' : '0rpx' }">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<text class="gui-spread-btn bg-white d-block opacity9" v-if="isBtn" @tap="spreadContent" :style="{fontSize:btnTxtSize, zIndex:zIndex, width:width}" > {{btnTxt}}</text>
|
||||
<text class="gui-spread-btn bg-white d-block opacity9" v-if="!isBtn && isShrink" @tap="shrinkContent" :style="{fontSize:btnTxtSize, zIndex:zIndex, width:width}">{{shrinkBtnTxt}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name : "i-spread",
|
||||
props : {
|
||||
width : { type : String, default : "690rpx" },
|
||||
height : { type : String, default : "600rpx" },
|
||||
btnTxt : { type : String, default : "展开全文" },
|
||||
btnTxtSize : { type : String, default : "28rpx" },
|
||||
zIndex : { type : Number, default : 1 },
|
||||
isShrink : { type : Boolean,default : false},
|
||||
shrinkBtnTxt: { type : String, default : "收起"}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reHeight: "600px",
|
||||
isBtn : true
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.reHeight = this.height;
|
||||
},
|
||||
methods: {
|
||||
spreadContent() {
|
||||
this.reHeight = '';
|
||||
this.isBtn = false;
|
||||
},
|
||||
shrinkContent () {
|
||||
this.reHeight = this.height;
|
||||
this.isBtn = true;
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.gui-spread-btn{height:91rpx; line-height:88rpx; position:absolute; z-index:999; left:0; bottom:-3rpx; text-align:center;font-size:28rpx;opacity:0.96;}
|
||||
</style>
|
70
components/i-swiper/i-swiper.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-swiper-dot :info="resdata" :current="current" :dots-styles="dotsStyles">
|
||||
<swiper :style="'height:'+height+'rpx'" @change="change">
|
||||
<swiper-item v-for="(item ,index) in resdata" :key="index" class=" overflow-hidden" :class="round?'rounded-lg':''">
|
||||
<view class="overflow-hidden" :class="round?'rounded-lg':''" @click="toShow(item)">
|
||||
<image :src="item" :style="'height:'+ height +'rpx'+';width:'+ width +'rpx'" mode="aspectFill"></image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</uni-swiper-dot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"iSwiper",
|
||||
props:{
|
||||
resdata: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
},
|
||||
width:{
|
||||
type: Number,
|
||||
default() {
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
height:{
|
||||
type: Number,
|
||||
default() {
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
round:{
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
current: 0,
|
||||
dotsStyles: {
|
||||
backgroundColor: 'rgba(255, 90, 95,0.3)',
|
||||
border: '1px rgba(255, 90, 95,0.3) solid',
|
||||
color: '#fff',
|
||||
selectedBackgroundColor: 'rgba(255, 90, 95,0.9)',
|
||||
selectedBorder: '1px rgba(255, 90, 95,0.9) solid'
|
||||
},
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
change(e) {
|
||||
this.current = e.detail.current
|
||||
},
|
||||
toShow(item){
|
||||
this.$emit('click',item)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
58
components/i-thumb-list/i-thumb-list.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 flex flex-row rounded-lg bg-white mt-2" v-for="(item,index) in resdata" :key="index" @click="toShow(item)" style="gap: 20rpx">
|
||||
<view class="flex-0" v-if="item.imgs.length > 0" style="flex-basis: 180rpx;">
|
||||
<image :src="item.imgs[0]" style="width:180rpx;height: 180rpx; border-radius: 16rpx;" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="flex-5 flex flex-column justify-between" style="height: 180rpx;">
|
||||
<view>
|
||||
<text class="font32 line15 text-ellipsis-2">{{item.content}}</text>
|
||||
</view>
|
||||
<view class="flex align-center justify-between">
|
||||
<view class="flex align-center">
|
||||
<image src="../../static/images/icon-time.png" style="height: 20rpx; width: 20rpx;"></image>
|
||||
<text class="font24 text-muted">{{item.create_at}}</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<image v-if="item.my_like > 0" src="../../static/images/icon-like.png" style="height: 20rpx; width: 20rpx;"></image>
|
||||
<image v-else src="../../static/images/icon-nolike.png" style="height: 20rpx; width: 20rpx;"></image>
|
||||
<text class="font24 text-muted">{{item.like_count}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-thumb-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
console.log(this.resdata)
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/thumb/detail?id='+item.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
46
components/i-tutorial-list/i-tutorial-list.vue
Normal file
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 rounded-lg bg-white mt-2" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<text class="font32 line15">{{item.title}}</text>
|
||||
<view class="flex align-center justify-between mt-2">
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="eye" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">{{item.view_count}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-tutorial-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
console.log(this.resdata)
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/tutorial/detail?id='+item.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
55
components/i-user-share-list/i-user-share-list.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 flex flex-row rounded-lg bg-white mt-2" v-for="(item,index) in resdata" :key="index" @click="toShow(item)" style="gap: 20rpx">
|
||||
<view class="flex-0" v-if="item.imgs.length > 0" style="flex-basis: 180rpx;">
|
||||
<image :src="item.imgs[0]" style="width:180rpx;height: 180rpx; border-radius: 16rpx;" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="flex-5 flex flex-column justify-between" style="height: 180rpx;">
|
||||
<view>
|
||||
<text class="font32 line15 text-ellipsis-2">{{item.content}}</text>
|
||||
<text v-if="item.status === 0" style="background-color: #FFBE0E; border-radius: 18rpx; padding: 0 12rpx; font-size: 18rpx;">未处理</text>
|
||||
<text v-else-if="item.status === 1" style="background-color: #4A8DFF; border-radius: 18rpx; padding: 0 12rpx; font-size: 18rpx;">已处理</text>
|
||||
</view>
|
||||
<view class="flex align-center justify-start">
|
||||
<view class="flex align-start">
|
||||
<image src="../../static/images/icon-time.png" style="height: 20rpx; width: 20rpx;"></image>
|
||||
<text class="font24 text-muted">{{item.create_at}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-user-share-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
console.log(this.resdata)
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/user-share/detail?id='+item.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
57
components/i-video-list/i-video-list.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="p-3 rounded-lg bg-white mt-2" v-for="(item,index) in resdata" :key="index" @click="toShow(item)">
|
||||
<text class="font32 line15">视频标题</text>
|
||||
<view class="mt-2 position-relative" >
|
||||
<view class="position-absolute left-0 right-0 top-0 bottom-0 flex align-center justify-center" style="z-index: 9;">
|
||||
<uni-icons type="videocam" size="40" color="#ffffff"></uni-icons>
|
||||
</view>
|
||||
<image src="/static/photo.jpg" style="width:650rpx;height: 350rpx;" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="flex align-center justify-between mt-1">
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="contact" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">小王</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="eye" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">111</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="calendar" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">222</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:"i-video-list",
|
||||
props:{
|
||||
resdata:{
|
||||
type:Array,
|
||||
default() {
|
||||
return [];
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
toShow(item){
|
||||
uni.navigateTo({
|
||||
url:'/pages/video/detail'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
137
components/pick-regions/pick-regions.vue
Normal file
@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<picker mode="multiSelector"
|
||||
:value="multiIndex"
|
||||
:range="multiArray"
|
||||
@change="handleValueChange"
|
||||
@columnchange="handleColumnChange">
|
||||
<slot></slot>
|
||||
</picker>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CHINA_REGIONS from './regions.json'
|
||||
export default {
|
||||
props:{
|
||||
defaultRegions:{
|
||||
type:Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
defaultRegionCode:{
|
||||
type:String
|
||||
},
|
||||
defaultRegion:[String,Array]
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cityArr:CHINA_REGIONS[0].childs,
|
||||
districtArr:CHINA_REGIONS[0].childs[0].childs,
|
||||
multiIndex: [0, 0, 0],
|
||||
isInitMultiArray:true,
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
defaultRegion:{
|
||||
handler(region,oldRegion){
|
||||
if(Array.isArray(region)){
|
||||
// 避免传的是字面量的时候重复触发
|
||||
oldRegion = oldRegion || []
|
||||
if(region.join('')!==oldRegion.join('')){
|
||||
this.handleDefaultRegion(region)
|
||||
}
|
||||
}else if(region&®ion.length == 6){
|
||||
this.handleDefaultRegion(region)
|
||||
}else{
|
||||
console.warn('defaultRegion非有效格式')
|
||||
}
|
||||
},
|
||||
immediate:true,
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
multiArray(){
|
||||
return this.pickedArr.map(arr=>arr.map(item=>item.name))
|
||||
},
|
||||
pickedArr(){
|
||||
// 进行初始化
|
||||
if(this.isInitMultiArray){
|
||||
return [
|
||||
CHINA_REGIONS,
|
||||
CHINA_REGIONS[0].childs,
|
||||
CHINA_REGIONS[0].childs[0].childs
|
||||
]
|
||||
}
|
||||
return [CHINA_REGIONS,this.cityArr,this.districtArr];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleColumnChange(e){
|
||||
// console.log(e);
|
||||
this.isInitMultiArray = false;
|
||||
const that = this;
|
||||
let col = e.detail.column;
|
||||
let row = e.detail.value;
|
||||
that.multiIndex[col] = row;
|
||||
try{
|
||||
switch(col){
|
||||
case 0:
|
||||
if(CHINA_REGIONS[that.multiIndex[0]].childs.length==0){
|
||||
that.cityArr = that.districtArr = [CHINA_REGIONS[that.multiIndex[0]]]
|
||||
break;
|
||||
}
|
||||
that.cityArr = CHINA_REGIONS[that.multiIndex[0]].childs
|
||||
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[that.multiIndex[1]].childs
|
||||
break;
|
||||
case 1:
|
||||
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[that.multiIndex[1]].childs
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
}catch(e){
|
||||
// console.log(e);
|
||||
that.districtArr = CHINA_REGIONS[that.multiIndex[0]].childs[0].childs
|
||||
}
|
||||
|
||||
},
|
||||
handleValueChange(e){
|
||||
// 结构赋值
|
||||
let [index0,index1,index2] = e.detail.value;
|
||||
let [arr0,arr1,arr2] = this.pickedArr;
|
||||
let address = [arr0[index0],arr1[index1],arr2[index2]];
|
||||
// console.log(address);
|
||||
this.$emit('getRegion',address)
|
||||
},
|
||||
handleDefaultRegion(region){
|
||||
const isCode = !Array.isArray(region)
|
||||
this.isInitMultiArray = false;
|
||||
let children = CHINA_REGIONS
|
||||
for(let i=0;i<3;i++){
|
||||
for(let j=0;j<children.length;j++){
|
||||
let condition = isCode?children[j].code==region.slice(0,(i+1)*2):children[j].name.includes(region[i]);
|
||||
if(condition){
|
||||
// 匹配成功进行赋值
|
||||
// console.log(i,j,children.length-1);
|
||||
children = children[j].childs;
|
||||
if(i==0){
|
||||
this.cityArr = children
|
||||
}else if(i==1){
|
||||
this.districtArr = children
|
||||
}
|
||||
this.$set(this.multiIndex,i,j)
|
||||
// console.log(this.multiIndex);
|
||||
break;
|
||||
}else{
|
||||
// 首次匹配失败就用默认的初始化
|
||||
// console.log(i,j,children.length-1);
|
||||
if(i==0 && j==(children.length-1)){
|
||||
this.isInitMultiArray = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
1
components/pick-regions/regions.json
Normal file
27
components/u-parse/components/wxParseAudio.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<!--增加audio标签支持-->
|
||||
<audio
|
||||
:id="node.attr.id"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:src="node.attr.src"
|
||||
:loop="node.attr.loop"
|
||||
:poster="node.attr.poster"
|
||||
:name="node.attr.name"
|
||||
:author="node.attr.author"
|
||||
controls></audio>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'wxParseAudio',
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
86
components/u-parse/components/wxParseImg.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<image
|
||||
:mode="node.attr.mode"
|
||||
:lazy-load="node.attr.lazyLoad"
|
||||
:class="node.classStr"
|
||||
:style="newStyleStr || node.styleStr"
|
||||
:data-src="node.attr.src"
|
||||
:src="node.attr.src"
|
||||
@tap="wxParseImgTap"
|
||||
@load="wxParseImgLoad"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'wxParseImg',
|
||||
data() {
|
||||
return {
|
||||
newStyleStr: '',
|
||||
preview: true,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
wxParseImgTap(e) {
|
||||
if (!this.preview) return;
|
||||
const { src } = e.currentTarget.dataset;
|
||||
if (!src) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.preview(src, e);
|
||||
},
|
||||
// 图片视觉宽高计算函数区
|
||||
wxParseImgLoad(e) {
|
||||
const { src } = e.currentTarget.dataset;
|
||||
if (!src) return;
|
||||
const { width, height } = e.mp ? e.mp.detail : e.detail;
|
||||
const recal = this.wxAutoImageCal(width, height);
|
||||
const { imageheight, imageWidth } = recal;
|
||||
const { padding, mode } = this.node.attr;
|
||||
const { styleStr } = this.node;
|
||||
const imageHeightStyle = mode === 'widthFix' ? '' : `height: ${imageheight}px;`;
|
||||
this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px; padding: 0 ${+padding}px;`;
|
||||
},
|
||||
// 计算视觉优先的图片宽高
|
||||
wxAutoImageCal(originalWidth, originalHeight) {
|
||||
// 获取图片的原始长宽
|
||||
const { padding } = this.node.attr;
|
||||
const windowWidth = this.node.$screen.width - (2 * padding);
|
||||
const results = {};
|
||||
|
||||
if (originalWidth < 60 || originalHeight < 60) {
|
||||
const { src } = this.node.attr;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.removeImageUrl(src);
|
||||
this.preview = false;
|
||||
}
|
||||
|
||||
// 判断按照那种方式进行缩放
|
||||
if (originalWidth > windowWidth) {
|
||||
// 在图片width大于手机屏幕width时候
|
||||
results.imageWidth = windowWidth;
|
||||
results.imageheight = windowWidth * (originalHeight / originalWidth);
|
||||
} else {
|
||||
// 否则展示原来的数据
|
||||
results.imageWidth = originalWidth;
|
||||
results.imageheight = originalHeight;
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
55
components/u-parse/components/wxParseTable.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<div class='tablebox'>
|
||||
<rich-text :nodes="nodes" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'wxParseTable',
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
inject: ['parseSelect'],
|
||||
data() {
|
||||
return {
|
||||
nodes:[]
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.nodes=this.loadNode([this.node]);
|
||||
},
|
||||
methods: {
|
||||
loadNode(node) {
|
||||
let obj = [];
|
||||
for (let children of node) {
|
||||
if (children.node=='element') {
|
||||
let t = {
|
||||
name:children.tag,
|
||||
attrs: {
|
||||
class: children.classStr,
|
||||
// style: children.styleStr,
|
||||
},
|
||||
children: children.nodes?this.loadNode(children.nodes):[]
|
||||
}
|
||||
|
||||
obj.push(t)
|
||||
} else if(children.node=='text'){
|
||||
obj.push({
|
||||
type: 'text',
|
||||
text: children.text
|
||||
})
|
||||
}
|
||||
}
|
||||
return obj
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
@import url("../parse.css");
|
||||
</style>
|
107
components/u-parse/components/wxParseTemplate0.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--table类型-->
|
||||
<block v-else-if="node.tag == 'table'">
|
||||
<view :class="node.classStr" class="table" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate1';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate0',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;// TODO currentTarget才有dataset
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
99
components/u-parse/components/wxParseTemplate1.vue
Normal file
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<view :class="(node.tag == 'li' ? node.classStr : (node.node==='text'?'text':''))">
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<!-- <view :class="node.classStr" :style="node.styleStr"> -->
|
||||
<view :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate2';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate1',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
97
components/u-parse/components/wxParseTemplate10.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate11';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate10',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
87
components/u-parse/components/wxParseTemplate11.vue
Normal file
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
{{node.text}}
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
{{node.text}}
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
{{node.text}}
|
||||
</view>
|
||||
</block>
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate11',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate2.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate3';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate2',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate3.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate4';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate3',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate4.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate5';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate4',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate5.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate6';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate5',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate6.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate7';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate6',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate7.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate8';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate7',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate8.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate9';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate8',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
98
components/u-parse/components/wxParseTemplate9.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<block v-if="node.tag == 'button'">
|
||||
<button type="default" size="mini">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</button>
|
||||
</block>
|
||||
|
||||
<!--li类型-->
|
||||
<block v-else-if="node.tag == 'li'">
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--video类型-->
|
||||
<block v-else-if="node.tag == 'video'">
|
||||
<wx-parse-video :node="node" />
|
||||
</block>
|
||||
|
||||
<!--audio类型-->
|
||||
<block v-else-if="node.tag == 'audio'">
|
||||
<wx-parse-audio :node="node" />
|
||||
</block>
|
||||
|
||||
<!--img类型-->
|
||||
<block v-else-if="node.tag == 'img'">
|
||||
<wx-parse-img :node="node" />
|
||||
</block>
|
||||
|
||||
<!--a类型-->
|
||||
<block v-else-if="node.tag == 'a'">
|
||||
<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--br类型-->
|
||||
<block v-else-if="node.tag == 'br'">
|
||||
<text>\n</text>
|
||||
</block>
|
||||
|
||||
<!--其他标签-->
|
||||
<block v-else>
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{node.text}}</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from './wxParseTemplate10';
|
||||
import wxParseImg from './wxParseImg';
|
||||
import wxParseVideo from './wxParseVideo';
|
||||
import wxParseAudio from './wxParseAudio';
|
||||
|
||||
export default {
|
||||
name: 'wxParseTemplate9',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(e) {
|
||||
const {
|
||||
href
|
||||
} = e.currentTarget.dataset;
|
||||
if (!href) return;
|
||||
let parent = this.$parent;
|
||||
while(!parent.preview || typeof parent.preview !== 'function') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
parent.navigate(href, e);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
15
components/u-parse/components/wxParseVideo.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<!--增加video标签支持,并循环添加-->
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<video :class="node.classStr" class="video-video" :src="node.attr.src"></video>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'wxParseVideo',
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
};
|
||||
</script>
|
261
components/u-parse/libs/html2json.js
Normal file
@ -0,0 +1,261 @@
|
||||
/**
|
||||
* html2Json 改造来自: https://github.com/Jxck/html2json
|
||||
*
|
||||
*
|
||||
* author: Di (微信小程序开发工程师)
|
||||
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
|
||||
* 垂直微信小程序开发交流社区
|
||||
*
|
||||
* github地址: https://github.com/icindy/wxParse
|
||||
*
|
||||
* for: 微信小程序富文本解析
|
||||
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
|
||||
*/
|
||||
|
||||
import wxDiscode from './wxDiscode';
|
||||
import HTMLParser from './htmlparser';
|
||||
|
||||
function makeMap(str) {
|
||||
const obj = {};
|
||||
const items = str.split(',');
|
||||
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Block Elements - HTML 5
|
||||
const block = makeMap('br,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
|
||||
|
||||
// Inline Elements - HTML 5
|
||||
const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
|
||||
|
||||
// Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
|
||||
|
||||
function removeDOCTYPE(html) {
|
||||
const isDocument = /<body.*>([^]*)<\/body>/.test(html);
|
||||
return isDocument ? RegExp.$1 : html;
|
||||
}
|
||||
|
||||
function trimHtml(html) {
|
||||
return html
|
||||
.replace(/<!--.*?-->/gi, '')
|
||||
.replace(/\/\*.*?\*\//gi, '')
|
||||
.replace(/[ ]+</gi, '<')
|
||||
.replace(/<script[^]*<\/script>/gi, '')
|
||||
.replace(/<style[^]*<\/style>/gi, '');
|
||||
}
|
||||
|
||||
function getScreenInfo() {
|
||||
const screen = {};
|
||||
wx.getSystemInfo({
|
||||
success: (res) => {
|
||||
screen.width = res.windowWidth;
|
||||
screen.height = res.windowHeight;
|
||||
},
|
||||
});
|
||||
return screen;
|
||||
}
|
||||
|
||||
function html2json(html, customHandler, imageProp, host) {
|
||||
// 处理字符串
|
||||
html = removeDOCTYPE(html);
|
||||
html = trimHtml(html);
|
||||
html = wxDiscode.strDiscode(html);
|
||||
// 生成node节点
|
||||
const bufArray = [];
|
||||
const results = {
|
||||
nodes: [],
|
||||
imageUrls: [],
|
||||
};
|
||||
|
||||
const screen = getScreenInfo();
|
||||
function Node(tag) {
|
||||
this.node = 'element';
|
||||
this.tag = tag;
|
||||
|
||||
this.$screen = screen;
|
||||
}
|
||||
|
||||
HTMLParser(html, {
|
||||
start(tag, attrs, unary) {
|
||||
// node for this element
|
||||
const node = new Node(tag);
|
||||
|
||||
if (bufArray.length !== 0) {
|
||||
const parent = bufArray[0];
|
||||
if (parent.nodes === undefined) {
|
||||
parent.nodes = [];
|
||||
}
|
||||
}
|
||||
|
||||
if (block[tag]) {
|
||||
node.tagType = 'block';
|
||||
} else if (inline[tag]) {
|
||||
node.tagType = 'inline';
|
||||
} else if (closeSelf[tag]) {
|
||||
node.tagType = 'closeSelf';
|
||||
}
|
||||
|
||||
node.attr = attrs.reduce((pre, attr) => {
|
||||
const { name } = attr;
|
||||
let { value } = attr;
|
||||
if (name === 'class') {
|
||||
node.classStr = value;
|
||||
}
|
||||
// has multi attibutes
|
||||
// make it array of attribute
|
||||
if (name === 'style') {
|
||||
node.styleStr = value;
|
||||
}
|
||||
if (value.match(/ /)) {
|
||||
value = value.split(' ');
|
||||
}
|
||||
|
||||
// if attr already exists
|
||||
// merge it
|
||||
if (pre[name]) {
|
||||
if (Array.isArray(pre[name])) {
|
||||
// already array, push to last
|
||||
pre[name].push(value);
|
||||
} else {
|
||||
// single value, make it array
|
||||
pre[name] = [pre[name], value];
|
||||
}
|
||||
} else {
|
||||
// not exist, put it
|
||||
pre[name] = value;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}, {});
|
||||
|
||||
// 优化样式相关属性
|
||||
if (node.classStr) {
|
||||
node.classStr += ` ${node.tag}`;
|
||||
} else {
|
||||
node.classStr = node.tag;
|
||||
}
|
||||
if (node.tagType === 'inline') {
|
||||
node.classStr += ' inline';
|
||||
}
|
||||
|
||||
// 对img添加额外数据
|
||||
if (node.tag === 'img') {
|
||||
let imgUrl = node.attr.src;
|
||||
imgUrl = wxDiscode.urlToHttpUrl(imgUrl, imageProp.domain);
|
||||
Object.assign(node.attr, imageProp, {
|
||||
src: imgUrl || '',
|
||||
});
|
||||
if (imgUrl) {
|
||||
results.imageUrls.push(imgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理a标签属性
|
||||
if (node.tag === 'a') {
|
||||
node.attr.href = node.attr.href || '';
|
||||
}
|
||||
|
||||
// 处理font标签样式属性
|
||||
if (node.tag === 'font') {
|
||||
const fontSize = [
|
||||
'x-small',
|
||||
'small',
|
||||
'medium',
|
||||
'large',
|
||||
'x-large',
|
||||
'xx-large',
|
||||
'-webkit-xxx-large',
|
||||
];
|
||||
const styleAttrs = {
|
||||
color: 'color',
|
||||
face: 'font-family',
|
||||
size: 'font-size',
|
||||
};
|
||||
if (!node.styleStr) node.styleStr = '';
|
||||
Object.keys(styleAttrs).forEach((key) => {
|
||||
if (node.attr[key]) {
|
||||
const value = key === 'size' ? fontSize[node.attr[key] - 1] : node.attr[key];
|
||||
node.styleStr += `${styleAttrs[key]}: ${value};`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 临时记录source资源
|
||||
if (node.tag === 'source') {
|
||||
results.source = node.attr.src;
|
||||
}
|
||||
|
||||
if (customHandler.start) {
|
||||
customHandler.start(node, results);
|
||||
}
|
||||
|
||||
if (unary) {
|
||||
// if this tag doesn't have end tag
|
||||
// like <img src="hoge.png"/>
|
||||
// add to parents
|
||||
const parent = bufArray[0] || results;
|
||||
if (parent.nodes === undefined) {
|
||||
parent.nodes = [];
|
||||
}
|
||||
parent.nodes.push(node);
|
||||
} else {
|
||||
bufArray.unshift(node);
|
||||
}
|
||||
},
|
||||
end(tag) {
|
||||
// merge into parent tag
|
||||
const node = bufArray.shift();
|
||||
if (node.tag !== tag) {
|
||||
console.error('invalid state: mismatch end tag');
|
||||
}
|
||||
|
||||
// 当有缓存source资源时于于video补上src资源
|
||||
if (node.tag === 'video' && results.source) {
|
||||
node.attr.src = results.source;
|
||||
delete results.source;
|
||||
}
|
||||
|
||||
if (customHandler.end) {
|
||||
customHandler.end(node, results);
|
||||
}
|
||||
|
||||
if (bufArray.length === 0) {
|
||||
results.nodes.push(node);
|
||||
} else {
|
||||
const parent = bufArray[0];
|
||||
if (!parent.nodes) {
|
||||
parent.nodes = [];
|
||||
}
|
||||
parent.nodes.push(node);
|
||||
}
|
||||
},
|
||||
chars(text) {
|
||||
if (!text.trim()) return;
|
||||
|
||||
const node = {
|
||||
node: 'text',
|
||||
text,
|
||||
};
|
||||
|
||||
if (customHandler.chars) {
|
||||
customHandler.chars(node, results);
|
||||
}
|
||||
|
||||
if (bufArray.length === 0) {
|
||||
results.nodes.push(node);
|
||||
} else {
|
||||
const parent = bufArray[0];
|
||||
if (parent.nodes === undefined) {
|
||||
parent.nodes = [];
|
||||
}
|
||||
parent.nodes.push(node);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export default html2json;
|
156
components/u-parse/libs/htmlparser.js
Normal file
@ -0,0 +1,156 @@
|
||||
/**
|
||||
*
|
||||
* htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
|
||||
*
|
||||
* author: Di (微信小程序开发工程师)
|
||||
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
|
||||
* 垂直微信小程序开发交流社区
|
||||
*
|
||||
* github地址: https://github.com/icindy/wxParse
|
||||
*
|
||||
* for: 微信小程序富文本解析
|
||||
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
|
||||
*/
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
|
||||
const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||
const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||
const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
|
||||
|
||||
function makeMap(str) {
|
||||
const obj = {};
|
||||
const items = str.split(',');
|
||||
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Empty Elements - HTML 5
|
||||
const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
|
||||
|
||||
// Block Elements - HTML 5
|
||||
const block = makeMap('address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
|
||||
|
||||
// Inline Elements - HTML 5
|
||||
const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
|
||||
|
||||
// Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
|
||||
|
||||
// Attributes that have their values filled in disabled="disabled"
|
||||
const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
|
||||
|
||||
function HTMLParser(html, handler) {
|
||||
let index;
|
||||
let chars;
|
||||
let match;
|
||||
let last = html;
|
||||
const stack = [];
|
||||
|
||||
stack.last = () => stack[stack.length - 1];
|
||||
|
||||
function parseEndTag(tag, tagName) {
|
||||
// If no tag name is provided, clean shop
|
||||
let pos;
|
||||
if (!tagName) {
|
||||
pos = 0;
|
||||
} else {
|
||||
// Find the closest opened tag of the same type
|
||||
tagName = tagName.toLowerCase();
|
||||
for (pos = stack.length - 1; pos >= 0; pos -= 1) {
|
||||
if (stack[pos] === tagName) break;
|
||||
}
|
||||
}
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (let i = stack.length - 1; i >= pos; i -= 1) {
|
||||
if (handler.end) handler.end(stack[i]);
|
||||
}
|
||||
|
||||
// Remove the open elements from the stack
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
|
||||
function parseStartTag(tag, tagName, rest, unary) {
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
if (block[tagName]) {
|
||||
while (stack.last() && inline[stack.last()]) {
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
}
|
||||
|
||||
if (closeSelf[tagName] && stack.last() === tagName) {
|
||||
parseEndTag('', tagName);
|
||||
}
|
||||
|
||||
unary = empty[tagName] || !!unary;
|
||||
|
||||
if (!unary) stack.push(tagName);
|
||||
|
||||
if (handler.start) {
|
||||
const attrs = [];
|
||||
|
||||
rest.replace(attr, function genAttr(matches, name) {
|
||||
const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
|
||||
|
||||
attrs.push({
|
||||
name,
|
||||
value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
|
||||
});
|
||||
});
|
||||
|
||||
if (handler.start) {
|
||||
handler.start(tagName, attrs, unary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (html) {
|
||||
chars = true;
|
||||
|
||||
if (html.indexOf('</') === 0) {
|
||||
match = html.match(endTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(endTag, parseEndTag);
|
||||
chars = false;
|
||||
}
|
||||
|
||||
// start tag
|
||||
} else if (html.indexOf('<') === 0) {
|
||||
match = html.match(startTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(startTag, parseStartTag);
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
index = html.indexOf('<');
|
||||
let text = '';
|
||||
while (index === 0) {
|
||||
text += '<';
|
||||
html = html.substring(1);
|
||||
index = html.indexOf('<');
|
||||
}
|
||||
text += index < 0 ? html : html.substring(0, index);
|
||||
html = index < 0 ? '' : html.substring(index);
|
||||
|
||||
if (handler.chars) handler.chars(text);
|
||||
}
|
||||
|
||||
if (html === last) throw new Error(`Parse Error: ${html}`);
|
||||
last = html;
|
||||
}
|
||||
|
||||
// Clean up any remaining tags
|
||||
parseEndTag();
|
||||
}
|
||||
|
||||
export default HTMLParser;
|
195
components/u-parse/libs/wxDiscode.js
Normal file
@ -0,0 +1,195 @@
|
||||
// HTML 支持的数学符号
|
||||
function strNumDiscode(str) {
|
||||
str = str.replace(/∀/g, '∀');
|
||||
str = str.replace(/∂/g, '∂');
|
||||
str = str.replace(/∃/g, '∃');
|
||||
str = str.replace(/∅/g, '∅');
|
||||
str = str.replace(/∇/g, '∇');
|
||||
str = str.replace(/∈/g, '∈');
|
||||
str = str.replace(/∉/g, '∉');
|
||||
str = str.replace(/∋/g, '∋');
|
||||
str = str.replace(/∏/g, '∏');
|
||||
str = str.replace(/∑/g, '∑');
|
||||
str = str.replace(/−/g, '−');
|
||||
str = str.replace(/∗/g, '∗');
|
||||
str = str.replace(/√/g, '√');
|
||||
str = str.replace(/∝/g, '∝');
|
||||
str = str.replace(/∞/g, '∞');
|
||||
str = str.replace(/∠/g, '∠');
|
||||
str = str.replace(/∧/g, '∧');
|
||||
str = str.replace(/∨/g, '∨');
|
||||
str = str.replace(/∩/g, '∩');
|
||||
str = str.replace(/∪/g, '∪');
|
||||
str = str.replace(/∫/g, '∫');
|
||||
str = str.replace(/∴/g, '∴');
|
||||
str = str.replace(/∼/g, '∼');
|
||||
str = str.replace(/≅/g, '≅');
|
||||
str = str.replace(/≈/g, '≈');
|
||||
str = str.replace(/≠/g, '≠');
|
||||
str = str.replace(/≤/g, '≤');
|
||||
str = str.replace(/≥/g, '≥');
|
||||
str = str.replace(/⊂/g, '⊂');
|
||||
str = str.replace(/⊃/g, '⊃');
|
||||
str = str.replace(/⊄/g, '⊄');
|
||||
str = str.replace(/⊆/g, '⊆');
|
||||
str = str.replace(/⊇/g, '⊇');
|
||||
str = str.replace(/⊕/g, '⊕');
|
||||
str = str.replace(/⊗/g, '⊗');
|
||||
str = str.replace(/⊥/g, '⊥');
|
||||
str = str.replace(/⋅/g, '⋅');
|
||||
return str;
|
||||
}
|
||||
|
||||
// HTML 支持的希腊字母
|
||||
function strGreeceDiscode(str) {
|
||||
str = str.replace(/Α/g, 'Α');
|
||||
str = str.replace(/Β/g, 'Β');
|
||||
str = str.replace(/Γ/g, 'Γ');
|
||||
str = str.replace(/Δ/g, 'Δ');
|
||||
str = str.replace(/Ε/g, 'Ε');
|
||||
str = str.replace(/Ζ/g, 'Ζ');
|
||||
str = str.replace(/Η/g, 'Η');
|
||||
str = str.replace(/Θ/g, 'Θ');
|
||||
str = str.replace(/Ι/g, 'Ι');
|
||||
str = str.replace(/Κ/g, 'Κ');
|
||||
str = str.replace(/Λ/g, 'Λ');
|
||||
str = str.replace(/Μ/g, 'Μ');
|
||||
str = str.replace(/Ν/g, 'Ν');
|
||||
str = str.replace(/Ξ/g, 'Ν');
|
||||
str = str.replace(/Ο/g, 'Ο');
|
||||
str = str.replace(/Π/g, 'Π');
|
||||
str = str.replace(/Ρ/g, 'Ρ');
|
||||
str = str.replace(/Σ/g, 'Σ');
|
||||
str = str.replace(/Τ/g, 'Τ');
|
||||
str = str.replace(/Υ/g, 'Υ');
|
||||
str = str.replace(/Φ/g, 'Φ');
|
||||
str = str.replace(/Χ/g, 'Χ');
|
||||
str = str.replace(/Ψ/g, 'Ψ');
|
||||
str = str.replace(/Ω/g, 'Ω');
|
||||
|
||||
str = str.replace(/α/g, 'α');
|
||||
str = str.replace(/β/g, 'β');
|
||||
str = str.replace(/γ/g, 'γ');
|
||||
str = str.replace(/δ/g, 'δ');
|
||||
str = str.replace(/ε/g, 'ε');
|
||||
str = str.replace(/ζ/g, 'ζ');
|
||||
str = str.replace(/η/g, 'η');
|
||||
str = str.replace(/θ/g, 'θ');
|
||||
str = str.replace(/ι/g, 'ι');
|
||||
str = str.replace(/κ/g, 'κ');
|
||||
str = str.replace(/λ/g, 'λ');
|
||||
str = str.replace(/μ/g, 'μ');
|
||||
str = str.replace(/ν/g, 'ν');
|
||||
str = str.replace(/ξ/g, 'ξ');
|
||||
str = str.replace(/ο/g, 'ο');
|
||||
str = str.replace(/π/g, 'π');
|
||||
str = str.replace(/ρ/g, 'ρ');
|
||||
str = str.replace(/ς/g, 'ς');
|
||||
str = str.replace(/σ/g, 'σ');
|
||||
str = str.replace(/τ/g, 'τ');
|
||||
str = str.replace(/υ/g, 'υ');
|
||||
str = str.replace(/φ/g, 'φ');
|
||||
str = str.replace(/χ/g, 'χ');
|
||||
str = str.replace(/ψ/g, 'ψ');
|
||||
str = str.replace(/ω/g, 'ω');
|
||||
str = str.replace(/ϑ/g, 'ϑ');
|
||||
str = str.replace(/ϒ/g, 'ϒ');
|
||||
str = str.replace(/ϖ/g, 'ϖ');
|
||||
str = str.replace(/·/g, '·');
|
||||
return str;
|
||||
}
|
||||
|
||||
function strcharacterDiscode(str) {
|
||||
// 加入常用解析
|
||||
str = str.replace(/ /g, ' ');
|
||||
str = str.replace(/ /g, ' ');
|
||||
str = str.replace(/ /g, ' ');
|
||||
str = str.replace(/"/g, "'");
|
||||
str = str.replace(/&/g, '&');
|
||||
str = str.replace(/</g, '<');
|
||||
str = str.replace(/>/g, '>');
|
||||
str = str.replace(/•/g, '•');
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// HTML 支持的其他实体
|
||||
function strOtherDiscode(str) {
|
||||
str = str.replace(/Œ/g, 'Œ');
|
||||
str = str.replace(/œ/g, 'œ');
|
||||
str = str.replace(/Š/g, 'Š');
|
||||
str = str.replace(/š/g, 'š');
|
||||
str = str.replace(/Ÿ/g, 'Ÿ');
|
||||
str = str.replace(/ƒ/g, 'ƒ');
|
||||
str = str.replace(/ˆ/g, 'ˆ');
|
||||
str = str.replace(/˜/g, '˜');
|
||||
str = str.replace(/ /g, '');
|
||||
str = str.replace(/ /g, '');
|
||||
str = str.replace(/ /g, '');
|
||||
str = str.replace(/‌/g, '');
|
||||
str = str.replace(/‍/g, '');
|
||||
str = str.replace(/‎/g, '');
|
||||
str = str.replace(/‏/g, '');
|
||||
str = str.replace(/–/g, '–');
|
||||
str = str.replace(/—/g, '—');
|
||||
str = str.replace(/‘/g, '‘');
|
||||
str = str.replace(/’/g, '’');
|
||||
str = str.replace(/‚/g, '‚');
|
||||
str = str.replace(/“/g, '“');
|
||||
str = str.replace(/”/g, '”');
|
||||
str = str.replace(/„/g, '„');
|
||||
str = str.replace(/†/g, '†');
|
||||
str = str.replace(/‡/g, '‡');
|
||||
str = str.replace(/•/g, '•');
|
||||
str = str.replace(/…/g, '…');
|
||||
str = str.replace(/‰/g, '‰');
|
||||
str = str.replace(/′/g, '′');
|
||||
str = str.replace(/″/g, '″');
|
||||
str = str.replace(/‹/g, '‹');
|
||||
str = str.replace(/›/g, '›');
|
||||
str = str.replace(/‾/g, '‾');
|
||||
str = str.replace(/€/g, '€');
|
||||
str = str.replace(/™/g, '™');
|
||||
|
||||
str = str.replace(/←/g, '←');
|
||||
str = str.replace(/↑/g, '↑');
|
||||
str = str.replace(/→/g, '→');
|
||||
str = str.replace(/↓/g, '↓');
|
||||
str = str.replace(/↔/g, '↔');
|
||||
str = str.replace(/↵/g, '↵');
|
||||
str = str.replace(/⌈/g, '⌈');
|
||||
str = str.replace(/⌉/g, '⌉');
|
||||
|
||||
str = str.replace(/⌊/g, '⌊');
|
||||
str = str.replace(/⌋/g, '⌋');
|
||||
str = str.replace(/◊/g, '◊');
|
||||
str = str.replace(/♠/g, '♠');
|
||||
str = str.replace(/♣/g, '♣');
|
||||
str = str.replace(/♥/g, '♥');
|
||||
|
||||
str = str.replace(/♦/g, '♦');
|
||||
str = str.replace(/'/g, "'");
|
||||
return str;
|
||||
}
|
||||
|
||||
function strDiscode(str) {
|
||||
str = strNumDiscode(str);
|
||||
str = strGreeceDiscode(str);
|
||||
str = strcharacterDiscode(str);
|
||||
str = strOtherDiscode(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
function urlToHttpUrl(url, domain) {
|
||||
if (/^\/\//.test(url)) {
|
||||
return `https:${url}`;
|
||||
} else if (/^\//.test(url)) {
|
||||
return `https://${domain}${url}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
export default {
|
||||
strDiscode,
|
||||
urlToHttpUrl,
|
||||
};
|
258
components/u-parse/parse.css
Normal file
@ -0,0 +1,258 @@
|
||||
/**
|
||||
* author: Di (微信小程序开发工程师)
|
||||
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
|
||||
* 垂直微信小程序开发交流社区
|
||||
*
|
||||
* github地址: https://github.com/icindy/wxParse
|
||||
*
|
||||
* for: 微信小程序富文本解析
|
||||
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
|
||||
*/
|
||||
/**
|
||||
* 请在全局下引入该文件,@import '/static/wxParse.css';
|
||||
*/
|
||||
.wxParse {
|
||||
user-select:none;
|
||||
width: 100%;
|
||||
font-family: Helvetica, "PingFangSC", 'Microsoft Yahei', '微软雅黑', Arial, sans-serif;
|
||||
color: #333;
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
text-align:justify;/* //左右两端对齐 */
|
||||
}
|
||||
.wxParse view ,.wxParse uni-view{
|
||||
word-break: break-word;
|
||||
}
|
||||
.wxParse .p {
|
||||
padding-bottom: 0.5em;
|
||||
clear: both;
|
||||
/* letter-spacing: 0;//字间距 */
|
||||
}
|
||||
.wxParse .inline {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wxParse .div {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wxParse .h1{
|
||||
font-size: 2em;
|
||||
line-height: 1.2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
.wxParse .h2{
|
||||
font-size: 1.5em;
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
.wxParse .h3{
|
||||
font-size: 1.17em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
.wxParse .h4{
|
||||
margin: 1.33em 0;
|
||||
}
|
||||
.wxParse .h5{
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
.wxParse .h6{
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
|
||||
.wxParse .h1,
|
||||
.wxParse .h2,
|
||||
.wxParse .h3,
|
||||
.wxParse .h4,
|
||||
.wxParse .h5,
|
||||
.wxParse .h6,
|
||||
.wxParse .b,
|
||||
.wxParse .strong{
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.wxParse .i,
|
||||
.wxParse .cite,
|
||||
.wxParse .em,
|
||||
.wxParse .var,
|
||||
.wxParse .address {
|
||||
font-style: italic;
|
||||
}
|
||||
.wxParse .spaceshow{
|
||||
white-space: pre;
|
||||
}
|
||||
.wxParse .pre,
|
||||
.wxParse .tt,
|
||||
.wxParse .code,
|
||||
.wxParse .kbd,
|
||||
.wxParse .samp {
|
||||
font-family: monospace;
|
||||
}
|
||||
.wxParse .pre {
|
||||
overflow: auto;
|
||||
background: #f5f5f5;
|
||||
padding: 16upx;
|
||||
white-space: pre;
|
||||
margin: 1em 0upx;
|
||||
font-size: 24upx;
|
||||
}
|
||||
.wxParse .code {
|
||||
overflow: auto;
|
||||
padding: 16upx;
|
||||
white-space: pre;
|
||||
margin: 1em 0upx;
|
||||
background: #f5f5f5;
|
||||
font-size: 24upx;
|
||||
}
|
||||
|
||||
.wxParse .big {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
.wxParse .small,
|
||||
.wxParse .sub,
|
||||
.wxParse .sup {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
|
||||
.wxParse .sub {
|
||||
vertical-align: sub;
|
||||
}
|
||||
.wxParse .sup {
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
.wxParse .s,
|
||||
.wxParse .strike,
|
||||
.wxParse .del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.wxParse .strong,
|
||||
.wxParse .text,
|
||||
.wxParse .span,
|
||||
.wxParse .s {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.wxParse .a {
|
||||
color: deepskyblue;
|
||||
}
|
||||
|
||||
.wxParse .video {
|
||||
text-align: center;
|
||||
margin: 22upx 0;
|
||||
}
|
||||
|
||||
.wxParse .video-video {
|
||||
width: 100%;
|
||||
}
|
||||
.wxParse .uni-image{
|
||||
max-width: 100%;
|
||||
}
|
||||
.wxParse .img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin-bottom: 0em;/* //与p标签底部padding同时修改 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wxParse .blockquote {
|
||||
margin: 10upx 0;
|
||||
padding: 22upx 0 22upx 22upx;
|
||||
font-family: Courier, Calibri, "宋体";
|
||||
background: #f5f5f5;
|
||||
border-left: 6upx solid #dbdbdb;
|
||||
}
|
||||
.wxParse .blockquote .p {
|
||||
margin: 0;
|
||||
}
|
||||
.wxParse .ul, .wxParse .ol {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
padding-left: 2em;
|
||||
}
|
||||
.wxParse .ol {
|
||||
list-style-type: disc;
|
||||
}
|
||||
.wxParse .ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
.wxParse .ol>weixin-parse-template,.wxParse .ul>weixin-parse-template {
|
||||
display: list-item;
|
||||
align-items: baseline;
|
||||
text-align: match-parent;
|
||||
}
|
||||
|
||||
.wxParse .ol>.li,.wxParse .ul>.li {
|
||||
display: list-item;
|
||||
align-items: baseline;
|
||||
text-align: match-parent;
|
||||
}
|
||||
.wxParse .ul .ul, .wxParse .ol .ul {
|
||||
list-style-type: circle;
|
||||
}
|
||||
.wxParse .ol .ol .ul, .wxParse .ol .ul .ul, .wxParse .ul .ol .ul, .wxParse .ul .ul .ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
.wxParse .u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.wxParse .hide {
|
||||
display: none;
|
||||
}
|
||||
.wxParse .del {
|
||||
display: inline;
|
||||
}
|
||||
.wxParse .figure {
|
||||
overflow: hidden;
|
||||
}
|
||||
.wxParse .tablebox{
|
||||
overflow: auto;
|
||||
background-color: #f5f5f5;
|
||||
background: #f5f5f5;
|
||||
font-size: 13px;
|
||||
padding: 8px;
|
||||
}
|
||||
.wxParse .table .table,.wxParse .table{
|
||||
border-collapse:collapse;
|
||||
box-sizing: border-box;
|
||||
/* 内边框 */
|
||||
/* width: 100%; */
|
||||
overflow: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
.wxParse .tbody{
|
||||
border-collapse:collapse;
|
||||
box-sizing: border-box;
|
||||
/* 内边框 */
|
||||
border: 1px solid #dadada;
|
||||
}
|
||||
.wxParse .table .thead, .wxParse .table .tfoot, .wxParse .table .th{
|
||||
border-collapse:collapse;
|
||||
box-sizing: border-box;
|
||||
background: #ececec;
|
||||
font-weight: 40;
|
||||
}
|
||||
.wxParse .table .tr {
|
||||
border-collapse:collapse;
|
||||
box-sizing: border-box;
|
||||
/* border: 2px solid #F0AD4E; */
|
||||
overflow:auto;
|
||||
}
|
||||
.wxParse .table .th,
|
||||
.wxParse .table .td{
|
||||
border-collapse:collapse;
|
||||
box-sizing: border-box;
|
||||
border: 2upx solid #dadada;
|
||||
overflow:auto;
|
||||
}
|
||||
.wxParse .audio, .wxParse .uni-audio-default{
|
||||
display: block;
|
||||
}
|
228
components/u-parse/parse.vue
Normal file
@ -0,0 +1,228 @@
|
||||
<!--**
|
||||
* forked from:https://github.com/F-loat/mpvue-wxParse
|
||||
*
|
||||
* github地址: https://github.com/dcloudio/uParse
|
||||
*
|
||||
* for: uni-app框架下 富文本解析
|
||||
*
|
||||
* 优化 by gaoyia@qq.com https://github.com/gaoyia/parse
|
||||
*/-->
|
||||
|
||||
<template>
|
||||
|
||||
<!--基础元素-->
|
||||
<div class="wxParse" :class="className" :style="'user-select:' + userSelect">
|
||||
<block v-for="(node, index) of nodes" :key="index" v-if="!loading">
|
||||
<wxParseTemplate :node="node" />
|
||||
</block>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HtmlToJson from './libs/html2json';
|
||||
import wxParseTemplate from './components/wxParseTemplate0';
|
||||
|
||||
|
||||
export default {
|
||||
name: 'wxParse',
|
||||
props: {
|
||||
// user-select:none;
|
||||
userSelect: {
|
||||
type: String,
|
||||
default: 'text' //none |text| all | element
|
||||
},
|
||||
imgOptions: {
|
||||
type: [Object, Boolean],
|
||||
default: function() {
|
||||
return {
|
||||
loop: false,
|
||||
indicator: 'number',
|
||||
longPressActions: false
|
||||
// longPressActions: {
|
||||
// itemList: ['发送给朋友', '保存图片', '收藏'],
|
||||
// success: function (res) {
|
||||
// console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
|
||||
// },
|
||||
// fail: function (res) {
|
||||
// console.log(res.errMsg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
noData: {
|
||||
type: String,
|
||||
default: '<div style="color: red;">数据不能为空</div>'
|
||||
},
|
||||
startHandler: {
|
||||
type: Function,
|
||||
default () {
|
||||
return node => {
|
||||
node.attr.class = null;
|
||||
node.attr.style = null;
|
||||
};
|
||||
}
|
||||
},
|
||||
endHandler: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
charsHandler: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
imageProp: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
mode: 'aspectFit',
|
||||
padding: 0,
|
||||
lazyLoad: false,
|
||||
domain: ''
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nodes: {},
|
||||
imageUrls: [],
|
||||
wxParseWidth: {
|
||||
value: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
this.setHtml()
|
||||
},
|
||||
methods: {
|
||||
setHtml() {
|
||||
this.getWidth().then((data) => {
|
||||
this.wxParseWidth.value = data;
|
||||
})
|
||||
let {
|
||||
content,
|
||||
noData,
|
||||
imageProp,
|
||||
startHandler,
|
||||
endHandler,
|
||||
charsHandler
|
||||
} = this;
|
||||
let parseData = content || noData;
|
||||
let customHandler = {
|
||||
start: startHandler,
|
||||
end: endHandler,
|
||||
chars: charsHandler
|
||||
};
|
||||
let results = HtmlToJson(parseData, customHandler, imageProp, this);
|
||||
|
||||
this.imageUrls = results.imageUrls;
|
||||
// this.nodes = results.nodes;
|
||||
|
||||
|
||||
this.nodes = [];
|
||||
results.nodes.forEach((item) => {
|
||||
setTimeout(() => {
|
||||
this.nodes.push(item)
|
||||
}, 0);
|
||||
})
|
||||
},
|
||||
getWidth() {
|
||||
return new Promise((res, rej) => {
|
||||
// #ifndef MP-ALIPAY || MP-BAIDU
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.wxParse')
|
||||
.fields({
|
||||
size: true,
|
||||
scrollOffset: true
|
||||
},
|
||||
data => {
|
||||
res(data.width);
|
||||
}
|
||||
).exec();
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
const query = swan.createSelectorQuery();
|
||||
query.select('.wxParse').boundingClientRect();
|
||||
query.exec(obj => {
|
||||
const rect = obj[0]
|
||||
if (rect) {
|
||||
res(rect.width);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
my.createSelectorQuery()
|
||||
.select('.wxParse')
|
||||
.boundingClientRect().exec((ret) => {
|
||||
res(ret[0].width);
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
},
|
||||
navigate(href, $event, attr) {
|
||||
console.log(href, attr);
|
||||
this.$emit('navigate', href, $event);
|
||||
},
|
||||
preview(src, $event) {
|
||||
if (!this.imageUrls.length || typeof this.imgOptions === 'boolean') {
|
||||
|
||||
} else {
|
||||
uni.previewImage({
|
||||
current: src,
|
||||
urls: this.imageUrls,
|
||||
loop: this.imgOptions.loop,
|
||||
indicator: this.imgOptions.indicator,
|
||||
longPressActions: this.imgOptions.longPressActions
|
||||
});
|
||||
}
|
||||
this.$emit('preview', src, $event);
|
||||
},
|
||||
removeImageUrl(src) {
|
||||
const {
|
||||
imageUrls
|
||||
} = this;
|
||||
imageUrls.splice(imageUrls.indexOf(src), 1);
|
||||
}
|
||||
},
|
||||
// 父组件中提供
|
||||
provide() {
|
||||
return {
|
||||
parseWidth: this.wxParseWidth,
|
||||
parseSelect: this.userSelect
|
||||
// 提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
content(){
|
||||
this.setHtml()
|
||||
}
|
||||
// content: {
|
||||
// handler: function(newVal, oldVal) {
|
||||
// if (newVal !== oldVal) {
|
||||
//
|
||||
// }
|
||||
// },
|
||||
// deep: true
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
102
components/u-parse/readme.md
Normal file
@ -0,0 +1,102 @@
|
||||
## uParse 适用于 uni-app/mpvue 的富文本解析组件
|
||||
|
||||
> 支持 Html、Markdown 解析,Fork自: [mpvue-wxParse](https://github.com/F-loat/mpvue-wxParse)
|
||||
|
||||
|
||||
## 属性
|
||||
|
||||
| 名称 | 类型 | 默认值 | 描述 |
|
||||
| -----------------|--------------- | ------------- | ---------------- |
|
||||
| loading | Boolean | false | 数据加载状态 |
|
||||
| className | String | — | 自定义 class 名称 |
|
||||
| content | String | — | 渲染内容 |
|
||||
| noData | String | 数据不能为空 | 空数据时的渲染展示 |
|
||||
| startHandler | Function | 见源码 | 自定义 parser 函数 |
|
||||
| endHandler | Function | null | 自定义 parser 函数 |
|
||||
| charsHandler | Function | null | 自定义 parser 函数 |
|
||||
| imageProp | Object | 见下文 | 图片相关参数 |
|
||||
|
||||
### 自定义 parser 函数具体介绍
|
||||
|
||||
* 传入的参数为当前节点 `node` 对象及解析结果 `results` 对象,例如 `startHandler(node, results)`
|
||||
* 无需返回值,通过对传入的参数直接操作来完成需要的改动
|
||||
* 自定义函数会在原解析函数处理之后执行
|
||||
|
||||
### imageProp 对象具体属性
|
||||
|
||||
| 名称 | 类型 | 默认值 | 描述 |
|
||||
| -----------------|--------------- | ------------- | ------------------ |
|
||||
| mode | String | 'aspectFit' | 图片裁剪、缩放的模式 |
|
||||
| padding | Number | 0 | 图片内边距 |
|
||||
| lazyLoad | Boolean | false | 图片懒加载 |
|
||||
| domain | String | '' | 图片服务域名 |
|
||||
|
||||
## 事件
|
||||
|
||||
| 名称 | 参数 | 描述 |
|
||||
| -----------------|----------------- | ---------------- |
|
||||
| preview | 图片地址,原始事件 | 预览图片时触发 |
|
||||
| navigate | 链接地址,原始事件 | 点击链接时触发 |
|
||||
|
||||
## 基本使用方法
|
||||
|
||||
|
||||
``` vue
|
||||
<template>
|
||||
<div>
|
||||
<u-parse :content="article" @preview="preview" @navigate="navigate" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uParse from '@/components/u-parse/u-parse.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uParse
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
article: '<div>我是HTML代码</div>'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
preview(src, e) {
|
||||
// do something
|
||||
},
|
||||
navigate(href, e) {
|
||||
// do something
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url("@/components/u-parse/u-parse.css");
|
||||
</style>
|
||||
```
|
||||
|
||||
|
||||
## 渲染 Markdown
|
||||
|
||||
> 先将 markdown 转换为 html 即可
|
||||
|
||||
```
|
||||
npm install marked
|
||||
```
|
||||
|
||||
``` js
|
||||
import marked from 'marked'
|
||||
import uParse from '@/components/u-parse/u-parse.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
uParse
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
article: marked(`#hello, markdown!`)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
232
components/u-parse/u-parse.css
Normal file
@ -0,0 +1,232 @@
|
||||
/**
|
||||
* author: Di (微信小程序开发工程师)
|
||||
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
|
||||
* 垂直微信小程序开发交流社区
|
||||
*
|
||||
* github地址: https://github.com/icindy/wxParse
|
||||
*
|
||||
* for: 微信小程序富文本解析
|
||||
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
|
||||
*/
|
||||
|
||||
.wxParse {
|
||||
width: 100%;
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 30upx;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.wxParse view {
|
||||
word-break: hyphenate;
|
||||
}
|
||||
|
||||
.wxParse .inline {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wxParse .div {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wxParse .h1 .text {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
.wxParse .h2 .text {
|
||||
font-size: 1.5em;
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
.wxParse .h3 .text {
|
||||
font-size: 1.17em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
.wxParse .h4 .text {
|
||||
margin: 1.33em 0;
|
||||
}
|
||||
.wxParse .h5 .text {
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
.wxParse .h6 .text {
|
||||
font-size: 0.67em;
|
||||
margin: 2.33em 0;
|
||||
}
|
||||
|
||||
.wxParse .h1 .text,
|
||||
.wxParse .h2 .text,
|
||||
.wxParse .h3 .text,
|
||||
.wxParse .h4 .text,
|
||||
.wxParse .h5 .text,
|
||||
.wxParse .h6 .text,
|
||||
.wxParse .b,
|
||||
.wxParse .strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
|
||||
.wxParse .p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.wxParse .i,
|
||||
.wxParse .cite,
|
||||
.wxParse .em,
|
||||
.wxParse .var,
|
||||
.wxParse .address {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.wxParse .pre,
|
||||
.wxParse .tt,
|
||||
.wxParse .code,
|
||||
.wxParse .kbd,
|
||||
.wxParse .samp {
|
||||
font-family: monospace;
|
||||
}
|
||||
.wxParse .pre {
|
||||
overflow: auto;
|
||||
background: #f5f5f5;
|
||||
padding: 16upx;
|
||||
white-space: pre;
|
||||
margin: 1em 0upx;
|
||||
}
|
||||
.wxParse .code {
|
||||
display: inline;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.wxParse .big {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
.wxParse .small,
|
||||
.wxParse .sub,
|
||||
.wxParse .sup {
|
||||
font-size: 0.83em;
|
||||
}
|
||||
|
||||
.wxParse .sub {
|
||||
vertical-align: sub;
|
||||
}
|
||||
.wxParse .sup {
|
||||
vertical-align: super;
|
||||
}
|
||||
|
||||
.wxParse .s,
|
||||
.wxParse .strike,
|
||||
.wxParse .del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.wxParse .strong,
|
||||
.wxParse .s {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.wxParse .a {
|
||||
color: deepskyblue;
|
||||
}
|
||||
|
||||
.wxParse .video {
|
||||
text-align: center;
|
||||
margin: 22upx 0;
|
||||
}
|
||||
|
||||
.wxParse .video-video {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wxParse .img {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wxParse .blockquote {
|
||||
margin: 10upx 0;
|
||||
padding: 22upx 0 22upx 22upx;
|
||||
font-family: Courier, Calibri, "宋体";
|
||||
background: #f5f5f5;
|
||||
border-left: 6upx solid #dbdbdb;
|
||||
}
|
||||
.wxParse .blockquote .p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wxParse .ul, .wxParse .ol {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
padding-left: 33upx;
|
||||
}
|
||||
.wxParse .ol {
|
||||
list-style-type: disc;
|
||||
}
|
||||
.wxParse .ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
.wxParse .ol>weixin-parse-template,.wxParse .ul>weixin-parse-template {
|
||||
display: list-item;
|
||||
align-items: baseline;
|
||||
text-align: match-parent;
|
||||
}
|
||||
|
||||
.wxParse .ol>.li,.wxParse .ul>.li {
|
||||
display: list-item;
|
||||
align-items: baseline;
|
||||
text-align: match-parent;
|
||||
}
|
||||
.wxParse .ul .ul, .wxParse .ol .ul {
|
||||
list-style-type: circle;
|
||||
}
|
||||
.wxParse .ol .ol .ul, .wxParse .ol .ul .ul, .wxParse .ul .ol .ul, .wxParse .ul .ul .ul {
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
.wxParse .u {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.wxParse .hide {
|
||||
display: none;
|
||||
}
|
||||
.wxParse .del {
|
||||
display: inline;
|
||||
}
|
||||
.wxParse .figure {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wxParse .table {
|
||||
width: 100%;
|
||||
}
|
||||
.wxParse .thead, .wxParse .tfoot, .wxParse .tr {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.wxParse .tr {
|
||||
width:100%;
|
||||
display: flex;
|
||||
border-right: 2upx solid #e0e0e0;
|
||||
border-bottom: 2upx solid #e0e0e0;
|
||||
}
|
||||
.wxParse .th,
|
||||
.wxParse .td {
|
||||
display: flex;
|
||||
width: 1276upx;
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
padding: 11upx;
|
||||
border-left: 2upx solid #e0e0e0;
|
||||
}
|
||||
.wxParse .td:last {
|
||||
border-top: 2upx solid #e0e0e0;
|
||||
}
|
||||
.wxParse .th {
|
||||
background: #f0f0f0;
|
||||
border-top: 2upx solid #e0e0e0;
|
||||
}
|
118
components/u-parse/u-parse.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<!--**
|
||||
* forked from:https://github.com/F-loat/mpvue-wxParse
|
||||
*
|
||||
* github地址: https://github.com/dcloudio/uParse
|
||||
*
|
||||
* for: uni-app框架下 富文本解析
|
||||
*/-->
|
||||
|
||||
<template>
|
||||
<!--基础元素-->
|
||||
<div class="wxParse" :class="className" v-if="!loading">
|
||||
<block v-for="(node,index) of nodes" :key="index">
|
||||
<wxParseTemplate :node="node" />
|
||||
</block>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HtmlToJson from './libs/html2json';
|
||||
import wxParseTemplate from './components/wxParseTemplate0';
|
||||
|
||||
export default {
|
||||
name: 'wxParse',
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
noData: {
|
||||
type: String,
|
||||
default: '<div style="color: red;">数据不能为空</div>',
|
||||
},
|
||||
startHandler: {
|
||||
type: Function,
|
||||
default() {
|
||||
return (node) => {
|
||||
node.attr.class = null;
|
||||
node.attr.style = null;
|
||||
};
|
||||
},
|
||||
},
|
||||
endHandler: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
charsHandler: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
imageProp: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
mode: 'aspectFit',
|
||||
padding: 0,
|
||||
lazyLoad: false,
|
||||
domain: '',
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imageUrls: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
nodes() {
|
||||
const {
|
||||
content,
|
||||
noData,
|
||||
imageProp,
|
||||
startHandler,
|
||||
endHandler,
|
||||
charsHandler,
|
||||
} = this;
|
||||
const parseData = content || noData;
|
||||
const customHandler = {
|
||||
start: startHandler,
|
||||
end: endHandler,
|
||||
chars: charsHandler,
|
||||
};
|
||||
const results = HtmlToJson(parseData, customHandler, imageProp, this);
|
||||
this.imageUrls = results.imageUrls;
|
||||
console.log(results)
|
||||
return results.nodes;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
navigate(href, $event) {
|
||||
this.$emit('navigate', href, $event);
|
||||
},
|
||||
preview(src, $event) {
|
||||
if (!this.imageUrls.length) return;
|
||||
wx.previewImage({
|
||||
current: src,
|
||||
urls: this.imageUrls,
|
||||
});
|
||||
this.$emit('preview', src, $event);
|
||||
},
|
||||
removeImageUrl(src) {
|
||||
const { imageUrls } = this;
|
||||
imageUrls.splice(imageUrls.indexOf(src), 1);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
20
index.html
Normal 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>
|
22
main.js
Normal file
@ -0,0 +1,22 @@
|
||||
import App from './App'
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
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
|
92
manifest.json
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"name" : "uni-guangan",
|
||||
"appid" : "__UNI__8389A82",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx8ebfd37103471d92",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"postcss" : true,
|
||||
"es6" : true,
|
||||
"minified" : true
|
||||
},
|
||||
"usingComponents" : true,
|
||||
"permission" : {
|
||||
"scope.userLocation" : {
|
||||
"desc" : "获取和定位问题位置"
|
||||
}
|
||||
},
|
||||
"requiredPrivateInfos" : [ "getLocation" ]
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3",
|
||||
"locale" : "zh-Hans",
|
||||
"fallbackLocale" : "zh-Hans",
|
||||
"h5" : {
|
||||
"sdkConfigs" : {
|
||||
"maps" : {
|
||||
"tencent" : {
|
||||
"key" : "NRFBZ-ZGV6Z-V6FXJ-73O4E-5ZW53-MYFCR"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
227
pages.json
Normal file
@ -0,0 +1,227 @@
|
||||
{
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "首页"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/user/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我的"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/news/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "文章详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/login",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "用户登录"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/points-mall/index",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "积分商城"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/point",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "我的积分"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user-share/user-share",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "随手拍"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/tutorial/tutorial",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "办事指南"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/tutorial/detail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "办事指南详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/message/message",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "我的消息"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/user_share",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "我的随手拍"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user-share/detail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "随手拍详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/thumb/thumb",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "城市点赞"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/thumb/list",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "城市点赞列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/const/help",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "帮助中心"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/const/about",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "关于我们"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/const/license",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "用户协议"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/const/privacy",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "隐私协议"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/const/more",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "更多设置"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/thumb/detail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "点赞城市详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/points-mall/detail",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "商品详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/points-mall/buy",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "确认兑换"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/address",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "收货地址管理"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/address_edit",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "编辑地址"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/order",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "订单列表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/info",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "账号管理"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/user/bind/bind",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "绑定手机"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "广安",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"uniIdRouter": {},
|
||||
"tabBar": {
|
||||
"color": "#555555",
|
||||
"selectedColor": "#2F85FC",
|
||||
"iconWidth": "128rpx",
|
||||
"list": [{
|
||||
"iconPath": "/static/images/icon-home-n.png",
|
||||
"selectedIconPath": "/static/images/icon-home.png",
|
||||
"pagePath": "pages/index/index",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"iconPath": "static/images/icon-dzcs-n.png",
|
||||
"selectedIconPath": "static/images/icon-dzcs.png",
|
||||
"pagePath": "pages/thumb/list",
|
||||
"text": "点赞城市"
|
||||
},
|
||||
{
|
||||
"iconPath": "static/images/icon-bszn-n.png",
|
||||
"selectedIconPath": "static/images/icon-bszn.png",
|
||||
"pagePath": "pages/tutorial/tutorial",
|
||||
"text": "办事指南"
|
||||
},
|
||||
{
|
||||
"iconPath": "static/images/icon-my-n.png",
|
||||
"selectedIconPath": "static/images/icon-my.png",
|
||||
"pagePath": "pages/user/index",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
22
pages/const/about.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<view>
|
||||
关于我们页面
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
22
pages/const/help.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<view>
|
||||
帮助页面
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
22
pages/const/license.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<view>
|
||||
用户条例
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
89
pages/const/more.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<view class="flex flex-column">
|
||||
<view class="center-list" @click="goHelp">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">帮助中心</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goAbout">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">关于我们</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">通知提醒</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goLicense">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">用户协议</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goPrivacy">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">隐私政策</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goHelp() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/const/help"
|
||||
})
|
||||
},
|
||||
goAbout() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/const/about"
|
||||
})
|
||||
},
|
||||
goLicense() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/const/license"
|
||||
})
|
||||
},
|
||||
goPrivacy() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/const/privacy"
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.center-list {
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
margin-top: 20upx;
|
||||
width: 690upx;
|
||||
margin-left: 30upx;
|
||||
margin-right: 30upx;
|
||||
}
|
||||
|
||||
.center-list-item {
|
||||
height: 90upx;
|
||||
width: 690upx;
|
||||
flex-direction: row;
|
||||
padding: 0upx 20upx;
|
||||
border-radius: 10upx;
|
||||
box-shadow: #55555555 1rpx 0rpx 2rpx 0rpx;
|
||||
}
|
||||
|
||||
.list-text {
|
||||
height: 90upx;
|
||||
line-height: 90upx;
|
||||
font-size: 34upx;
|
||||
color: #555;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
22
pages/const/privacy.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<view>
|
||||
隐私政策
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
299
pages/index/index.vue
Normal file
@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width: 100vw;">
|
||||
<view style="height: 300rpx;" v-if="bannerList.length > 0">
|
||||
<swiper interval="5000" :autoplay="true" :circular="true">
|
||||
<swiper-item class="flex" v-for="(item, index) in bannerList" :key="index">
|
||||
<image :src="item.image" mode="aspectFill" style="height: 300rpx;width: 100%;"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<i-loading v-if="loading" />
|
||||
<view class="icon-container">
|
||||
<view class="icon-block" @click="gotoUserShare">
|
||||
<image src="/static/images/icon-photograph.png" alt="随手拍" class="icon-img"></image>
|
||||
<text class="icon-text">随手拍</text>
|
||||
</view>
|
||||
<view class="icon-block" @click="gotoShop">
|
||||
<image src="/static/images/icon-store.png" alt="" class="icon-img"></image>
|
||||
<text class="icon-text">积分商城</text>
|
||||
</view>
|
||||
<view class="icon-block" @click="gotoTutorial">
|
||||
<image src="/static/images/icon-guide.png" alt="办事指南" class="icon-img"></image>
|
||||
<text class="icon-text">办事指南</text>
|
||||
</view>
|
||||
<view class="icon-block" @click="gotoThumbsUp">
|
||||
<image src="/static/images/icon-city.png" alt="" class="icon-img"></image>
|
||||
<text class="icon-text">点赞城市</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex flex-column flex-1">
|
||||
<view>
|
||||
<scroll-view class="flex-1" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2">
|
||||
<i-news-list :resdata="newsList" />
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
bannerList: [],
|
||||
tabBars: [{
|
||||
id: '',
|
||||
name: '全部'
|
||||
}],
|
||||
tabIndex: 0,
|
||||
newsList: [],
|
||||
curPage: 1,
|
||||
loading: false,
|
||||
refresh: false,
|
||||
finish: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
TaAjax.get('/cms/api.category/index').then((res) => {
|
||||
const data = res.data;
|
||||
data.forEach((item) => {
|
||||
this.tabBars.push(item)
|
||||
})
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
TaAjax.get('/cms/api.banner/index').then((res) => {
|
||||
const data = res.data;
|
||||
data.forEach((item) => {
|
||||
this.bannerList.push(item)
|
||||
})
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.refreshData();
|
||||
},
|
||||
methods: {
|
||||
changeTab(index) {
|
||||
this.tabIndex = index
|
||||
},
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.newsList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get('/cms/api.article/index', {
|
||||
cid: this.tabBars[this.tabIndex].id,
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.data.map((news) => {
|
||||
news.publish_at = friendlyDate(new Date(news.publish_at.replace(/\-/g, '/'))
|
||||
.getTime())
|
||||
news.imgs = news.thumb ? [news.thumb] : [];
|
||||
return news;
|
||||
});
|
||||
if (this.refresh) {
|
||||
this.newsList.length = 0;
|
||||
}
|
||||
this.newsList = this.newsList.concat(data_list);
|
||||
this.finish = data.total <= this.newsList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.newsList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
swiperChange(e) {
|
||||
this.tabIndex = e.detail.current
|
||||
this.refreshData()
|
||||
},
|
||||
gotoShop() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/points-mall/index",
|
||||
})
|
||||
},
|
||||
gotoTutorial() {
|
||||
uni.switchTab({
|
||||
url: "/pages/tutorial/tutorial"
|
||||
})
|
||||
},
|
||||
gotoUserShare() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user-share/user-share"
|
||||
})
|
||||
},
|
||||
gotoThumbsUp() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/thumb/thumb"
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background-color: #ffffff;
|
||||
/* #ifdef MP-ALIPAY || MP-BAIDU */
|
||||
height: 100vh;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 42px;
|
||||
flex-direction: row;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.tab-bar ::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.scroll-view-indicator {
|
||||
position: relative;
|
||||
height: 2px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.scroll-view-underline {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 0;
|
||||
background-color: #007AFF;
|
||||
}
|
||||
|
||||
.scroll-view-animation {
|
||||
transition-duration: 0.2s;
|
||||
transition-property: left;
|
||||
}
|
||||
|
||||
.tab-bar-line {
|
||||
height: 1px;
|
||||
background-color: #cccccc;
|
||||
}
|
||||
|
||||
.tab-box {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-tab-item {
|
||||
/* #ifndef APP-PLUS */
|
||||
display: inline-block;
|
||||
/* #endif */
|
||||
flex-wrap: nowrap;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.uni-tab-item-title {
|
||||
color: #555;
|
||||
font-size: 15px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
flex-wrap: nowrap;
|
||||
/* #ifndef APP-PLUS */
|
||||
white-space: nowrap;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-tab-item-title-active {
|
||||
color: #007AFF;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.page-item {
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
height: 160rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.icon-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.icon-img {
|
||||
border-radius:16rpx;
|
||||
height: 100rpx;
|
||||
width: 100rpx;
|
||||
}
|
||||
.icon-text {
|
||||
font-size: 24rpx;
|
||||
color: #555;
|
||||
}
|
||||
</style>
|
90
pages/message/message.vue
Normal file
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="flex flex-column flex-1">
|
||||
<scroll-view class="flex-1" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2">
|
||||
<i-message-list :resdata="messageList" />
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
messageList: [],
|
||||
curPage: 1,
|
||||
loading: true,
|
||||
refresh: true,
|
||||
finish: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.messageList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get('/custom/api.auth.Message/index', {
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.data.map((item) => {
|
||||
item.create_at = friendlyDate(new Date(item.create_at.replace(/\-/g, '/'))
|
||||
.getTime())
|
||||
return item;
|
||||
});
|
||||
if (this.refresh) {
|
||||
this.messageList.length = 0;
|
||||
}
|
||||
this.messageList = this.messageList.concat(data_list);
|
||||
this.finish = data.total <= this.messageList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.messageList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
78
pages/news/detail.vue
Normal file
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<view class="px-3">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="mt-2 font40 line15">{{newsInfo.title}}</view>
|
||||
<view class="bg-hover-light p-2 mt-2 rounded flex align-center justify-between flex-wrap font24">
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="contact" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">{{newsInfo.author}}</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="eye" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">{{newsInfo.view_count}}</text>
|
||||
</view>
|
||||
<view class="flex align-center">
|
||||
<uni-icons type="calendar" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 text-muted">{{newsInfo.publish_at}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-2">
|
||||
<u-parse :content="content" @preview="preview" @navigate="navigate"></u-parse>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { friendlyDate } from '../../common/util';
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
id: 0,
|
||||
content: "",
|
||||
newsInfo: {
|
||||
title: "",
|
||||
from: "",
|
||||
source: "",
|
||||
publish_at: "",
|
||||
view_count: 0,
|
||||
},
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
onLoad(params) {
|
||||
this.id = params.id
|
||||
this.loading = true;
|
||||
TaAjax.get('/cms/api.article/info', {
|
||||
id: this.id
|
||||
}).then((response) => {
|
||||
const data = response.data;
|
||||
this.content = data.content;
|
||||
uni.setNavigationBarTitle({
|
||||
title: data.title
|
||||
});
|
||||
data.publish_at = friendlyDate((new Date(data.publish_at.replace(/\-/g, '/')).getTime()))
|
||||
this.newsInfo = data;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
preview(src, e) {
|
||||
// do something
|
||||
},
|
||||
navigate(href, e) {
|
||||
// do something
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
161
pages/points-mall/buy.vue
Normal file
@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<view >
|
||||
<i-loading v-if="loading || address_loading"></i-loading>
|
||||
<view class="flex align-center justify-center bg-white p-3" @click="toAddress" v-if="!address_id">
|
||||
<view class="text-center">
|
||||
<uni-icons type="plusempty" size="20" color="#999999"></uni-icons>
|
||||
<view class="text-muted font28 mt-2">请选择收货地址</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bg-white p-3 flex align-center" @click="toAddress" v-else>
|
||||
<uni-icons type="location" size="20" color="#333333"></uni-icons>
|
||||
<view class="flex-1 mx-2">
|
||||
<view class="flex align-center font32">
|
||||
<text>{{address.user_name}}</text>
|
||||
<text class="ml-3">{{address.user_phone}}</text>
|
||||
</view>
|
||||
<view class="mt-1 font30 line15">{{address.region_prov}}{{address.region_city}}{{address.region_area}}{{address.region_addr}}</view>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#999999"></uni-icons>
|
||||
</view>
|
||||
<view class=" mt-2 bg-white">
|
||||
<view class="flex align-center justify-between p-3 border-bottom">
|
||||
<text class="font28 text-muted">订单编号</text>
|
||||
<view class="">{{order.order_no}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class=" mt-2 bg-white">
|
||||
<view class="flex align-center justify-between p-3 border-bottom">
|
||||
<text class="font28 text-muted">商品积分</text>
|
||||
<view class="cny_jf font-weight-bold">{{order.amount_goods}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-2 bg-white p-3" v-if="false">
|
||||
<view class="font30 mr-2">备注信息</view>
|
||||
<textarea placeholder="请输入备注信息" class="font30 mt-2 w-100" style="height: 100rpx;"></textarea>
|
||||
</view>
|
||||
<view class="cu-tabbar-height"></view>
|
||||
<view class="fixed-bottom bg-white py-2 border-top">
|
||||
<view class="flex align-center justify-between px-3">
|
||||
<view class="flex align-center font32">
|
||||
<text class="text-muted">消耗:</text>
|
||||
<view class="cny_jf font-weight-bold">{{order.amount_total}}</view>
|
||||
</view>
|
||||
<view class="bg-danger text-white px-4 rounded-circle py-2 font30" @click="toPay">立即兑换</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
address_loading: false,
|
||||
address_id: 0,
|
||||
address: {},
|
||||
loading: false,
|
||||
order_no: "",
|
||||
order: {},
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.order_no = e.order_no
|
||||
if (!this.order_no) {
|
||||
uni.showToast({
|
||||
title: '参数错误',
|
||||
icon: 'none',
|
||||
complete() {
|
||||
uni.navigateBack()
|
||||
}
|
||||
})
|
||||
}
|
||||
this.address_id = e.address_id
|
||||
if (this.address_id) {
|
||||
this.loadAddress()
|
||||
}
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.loading = true
|
||||
TaAjax.get('/points_mall/api.auth.order/get', {
|
||||
order_no: this.order_no,
|
||||
}).then(res => {
|
||||
const data = res.data
|
||||
this.order = data.list[0]
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
loadAddress() {
|
||||
this.address_loading = true
|
||||
TaAjax.get('/points_mall/api.auth.address/info', {
|
||||
id: this.address_id,
|
||||
}).then(res => {
|
||||
this.address = res.data
|
||||
}).finally(() => {
|
||||
this.address_loading = false
|
||||
})
|
||||
},
|
||||
toPay(){
|
||||
if (!this.address_id) {
|
||||
return uni.showToast({
|
||||
title: '请选择收货地址',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
uni.showLoading({
|
||||
title: '兑换中',
|
||||
})
|
||||
TaAjax.post('/points_mall/api.auth.order/perfect', {
|
||||
order_no: this.order_no,
|
||||
address_id: this.address_id,
|
||||
}).then(res => {
|
||||
if (res.code == 1) {
|
||||
TaAjax.post('/points_mall/api.auth.order/payment', {
|
||||
order_no: this.order_no,
|
||||
}).then(payRes => {
|
||||
if (payRes.code == 1) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: "兑换成功",
|
||||
icon: 'success',
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: payRes.info,
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: res.info,
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: "网络异常",
|
||||
icon: 'none',
|
||||
})
|
||||
})
|
||||
},
|
||||
toAddress(){
|
||||
uni.redirectTo({
|
||||
url:'/pages/user/address?order_no='+this.order_no
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
111
pages/points-mall/detail.vue
Normal file
@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<view>
|
||||
<i-swiper :resdata="piclist" :width="750" :height="750" :round='false' />
|
||||
<view class="bg-white p-3">
|
||||
<view class="flex align-center">
|
||||
<!-- <text class="d-inline-block bg-danger font20 text-white px-1 line2 rounded mr-1">秒杀</text> -->
|
||||
<view class="flex-1 text-ellipsis-1 font32">{{goodsInfo.name}}</view>
|
||||
</view>
|
||||
<view class=" flex align-end mt-2">
|
||||
<view class="text-danger">
|
||||
<text class="cny_jf">{{goodsInfo.price_selling}}</text>
|
||||
</view>
|
||||
<view class="font24 text-through cny ml-2 text-muted">{{goodsInfo.price_market}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-2 bg-white p-3">
|
||||
<view class="font32 font-weight-bold">图文详情</view>
|
||||
<i-spread width="690rpx" height="2000rpx" :isShrink="true">
|
||||
<u-parse :content="goodsInfo.content" @preview="preview" @navigate="navigate"></u-parse>
|
||||
</i-spread>
|
||||
</view>
|
||||
<view class="cu-tabbar-height"></view>
|
||||
<view class="bg-white fixed-bottom">
|
||||
<view class=" px-2 py-1 border-top flex align-center">
|
||||
<view class="flex-1 flex align-center ">
|
||||
<view class="text-center flex-1" @click="toIndex">
|
||||
<uni-icons type="home" size="20" color="#333333"></uni-icons>
|
||||
<view class="font24">首页</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-2 flex align-center ml-2">
|
||||
<view class="bg-danger text-white text-center py-2 font30 line15 rounded-circle flex-1" @click="toEvaluate">立即兑换</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
code: 0,
|
||||
goodsInfo: {},
|
||||
piclist: [],
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.code = e.code
|
||||
if (!this.code) {
|
||||
uni.showToast({
|
||||
title: '参数错误',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
complete() {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
TaAjax.get('/points_mall/api.goods/get', {
|
||||
code: this.code
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.list;
|
||||
this.goodsInfo = data_list[0];
|
||||
this.piclist = this.goodsInfo.slider
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
}).finally(() => {
|
||||
});
|
||||
},
|
||||
toIndex(){
|
||||
uni.switchTab({
|
||||
url:'/pages/points-mall/index'
|
||||
})
|
||||
},
|
||||
toEvaluate(){
|
||||
uni.showLoading({
|
||||
title: '加载中',
|
||||
})
|
||||
TaAjax.post('/points_mall/api.auth.order/add_goods', {
|
||||
code: this.code
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const order_no = data.order_no;
|
||||
uni.navigateTo({
|
||||
url:'/pages/points-mall/buy?order_no='+order_no
|
||||
})
|
||||
}).finally(() => {
|
||||
uni.hideLoading()
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bg-light-danger {
|
||||
background-color: #fad8d6;
|
||||
}
|
||||
</style>
|
82
pages/points-mall/index.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="flex flex-column flex-1">
|
||||
<scroll-view class="flex-1" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2">
|
||||
<i-list-top :resdata="goodsList"></i-list-top>
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax';
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsList: [],
|
||||
curPage: 1,
|
||||
loading: true,
|
||||
refresh: true,
|
||||
finish: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.goodsList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
TaAjax.get('/points_mall/api.goods/get', {
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.list;
|
||||
if (this.refresh) {
|
||||
this.goodsList.length = 0;
|
||||
}
|
||||
this.goodsList = this.goodsList.concat(data_list);
|
||||
this.finish = data.total <= this.goodsList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.goodsList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
75
pages/thumb/detail.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading"></i-loading>
|
||||
<view class="bg-white px-3 pb-3 mx-2 rounded-lg mt-2">
|
||||
<view class="pt-3 font30">
|
||||
<view class="text-muted">点赞内容</view>
|
||||
<view class="mt-2">{{info.content}}</view>
|
||||
</view>
|
||||
<view class="flex align-center justify-between pt-3 font30">
|
||||
<view class="text-muted">点赞时间</view>
|
||||
<view>{{info.create_at}}</view>
|
||||
</view>
|
||||
<view class="pt-3 font30" v-if="info.imgs_arr.length > 0">
|
||||
<view class="text-muted">图片</view>
|
||||
<view class="mt-2">
|
||||
<image v-for="(item, index) in info.imgs_arr" :key="index" :src="item" mode="aspectFill" class="rounded-lg" style="width: 100px;height: 100px;margin-right: 10px;" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaCache } from '../../common/cache';
|
||||
import { TaAjax } from '@/common/ajax'
|
||||
|
||||
export default {
|
||||
onLoad(options) {
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (!userInfo) {
|
||||
this.login = false
|
||||
} else {
|
||||
this.login = true
|
||||
}
|
||||
this.id = options.id
|
||||
if (!this.id) {
|
||||
uni.showToast({
|
||||
title: '缺少参数',
|
||||
icon: 'none'
|
||||
})
|
||||
return uni.navigateBack()
|
||||
}
|
||||
this.loadInfo()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: 0,
|
||||
loading: false,
|
||||
login: false,
|
||||
info: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadInfo() {
|
||||
this.loading = true
|
||||
TaAjax.get((this.login ? '/cms/api.auth.Thumb/info?id=' : '/cms/api.Thumb/info?id=') + this.id).then(res => {
|
||||
console.log(res)
|
||||
this.info = res.data
|
||||
}).catch(err => {
|
||||
uni.showToast({
|
||||
title: err.info,
|
||||
icon: 'error',
|
||||
})
|
||||
uni.navigateBack()
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
102
pages/thumb/list.vue
Normal file
@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<view class="flex flex-column flex-1" style="height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="flex flex-column flex-1">
|
||||
<scroll-view class="flex-1" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2">
|
||||
<i-thumb-list :resdata="shareList" />
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { TaCache } from '@/common/cache';
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shareList: [],
|
||||
curPage: 1,
|
||||
loading: true,
|
||||
refresh: true,
|
||||
finish: false,
|
||||
login: false
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (!userInfo) {
|
||||
this.login = false
|
||||
} else {
|
||||
this.login = true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.shareList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get(this.login ? '/cms/api.auth.Thumb/index' : '/cms/api.Thumb/index', {
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.data.map((share) => {
|
||||
share.create_at = friendlyDate(new Date(share.publish_at.replace(/\-/g, '/'))
|
||||
.getTime());
|
||||
share.imgs = share.imgs_arr;
|
||||
return share;
|
||||
});
|
||||
if (this.refresh) {
|
||||
this.shareList.length = 0;
|
||||
}
|
||||
this.shareList = this.shareList.concat(data_list);
|
||||
this.finish = data.total <= this.shareList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.shareList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
129
pages/thumb/thumb.vue
Normal file
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh; background-color: #F5F6F8;">
|
||||
<view class="bg-white mt-2 p-2 rounded-lg" style="padding-bottom: 200rpx;">
|
||||
<view class="flex-1 pt-3" style="color: #666666;">点赞城市内容:</view>
|
||||
<view class="border border-light rounded py-3 flex align-center justify-between" style="height: 200rpx;">
|
||||
<textarea v-model="form.content" autoHeight class="flex-1 font28" placeholder="点赞城市内容" />
|
||||
</view>
|
||||
<view class="flex-1 py-3">相关图片:</view>
|
||||
<view class="flex py-3 mb-6">
|
||||
<div class="flex flex-wrap w-25 position-relative" v-for="(item,index) in img_array" :key='index'>
|
||||
<img class="img-add" :src="item" @click="previewImage(index)" alt=""/>
|
||||
<img class='img-delete position-absolute' src='/static/images/delete.png' @click='deleteImage(index)'>
|
||||
</div>
|
||||
<div class="flex flex-wrap w-25" @click="chooseImages()">
|
||||
<img class='img-add' src="/static/images/addImage.png" alt="">
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fixed-bottom border-top bg-white py-2 px-3">
|
||||
<view class="bg-danger py-3 font30 text-center text-white shadow rounded-circle" @click="onSubmit">
|
||||
立即提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaCache } from '@/common/cache';
|
||||
import {
|
||||
TaAjax, TaPost, baseUrl
|
||||
} from '@/common/ajax';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
title: "点赞城市",
|
||||
content: "",
|
||||
imgs: "",
|
||||
},
|
||||
img_array: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const that = this;
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (!userInfo) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
chooseImages() {
|
||||
const that = this;
|
||||
uni.chooseMedia({
|
||||
mediaType: ['image', 'video'],
|
||||
sourceType: ['album', 'camera'],
|
||||
sizeType: ['original'],
|
||||
success(res) {
|
||||
for(let i=0;i<res.tempFiles.length;i++){
|
||||
const tempFilePath = res.tempFiles[i].tempFilePath
|
||||
const loadingId = uni.showLoading({
|
||||
title: '上传中...',
|
||||
mask: true,
|
||||
})
|
||||
uni.uploadFile({
|
||||
url: baseUrl + '/custom/api.Upload/file',
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
success(res) {
|
||||
const responseStr = res.data;
|
||||
const response = JSON.parse(res.data);
|
||||
const data = response.data;
|
||||
const url = data.url;
|
||||
that.img_array.push(url);
|
||||
},
|
||||
complete() {
|
||||
uni.hideLoading(loadingId)
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
previewImage(idx = 0) {
|
||||
uni.previewImage({
|
||||
urls: this.img_array,
|
||||
current: idx,
|
||||
loop: true,
|
||||
})
|
||||
},
|
||||
deleteImage(idx) {
|
||||
this.img_array.splice(idx, 1)
|
||||
},
|
||||
onSubmit() {
|
||||
this.form.images = this.img_array.join("|")
|
||||
TaPost('/cms/api.auth.Thumb/add', this.form).then((result) => {
|
||||
if (result.code == 0) {
|
||||
return uni.showToast({
|
||||
icon: 'error',
|
||||
title: result.info,
|
||||
})
|
||||
}
|
||||
const id = result.data
|
||||
uni.switchTab({
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
return uni.showToast({
|
||||
icon: 'success',
|
||||
title: result.info,
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.img-add {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
}
|
||||
.img-delete {
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 48rpx;
|
||||
width: 48rpx;
|
||||
}
|
||||
</style>
|
64
pages/tutorial/detail.vue
Normal file
@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="mt-2 font40 line15">{{newsInfo.title}}</view>
|
||||
<scroll-view>
|
||||
<view class="mt-2">
|
||||
<u-parse :content="newsInfo.content" @preview="preview" @navigate="navigate"></u-parse>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { friendlyDate } from '../../common/util';
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
id: 0,
|
||||
newsInfo: {
|
||||
title: "",
|
||||
content: "",
|
||||
material: "",
|
||||
method: "",
|
||||
view_count: 0,
|
||||
},
|
||||
loading: true
|
||||
}
|
||||
},
|
||||
onLoad(params) {
|
||||
this.id = params.id
|
||||
this.loading = true;
|
||||
TaAjax.get('/cms/api.tutorial/info', {
|
||||
id: this.id
|
||||
}).then((response) => {
|
||||
if (response.code == 0) {
|
||||
uni.showToast({
|
||||
title: response.info
|
||||
})
|
||||
return uni.navigateBack()
|
||||
}
|
||||
const data = response.data;
|
||||
uni.setNavigationBarTitle({
|
||||
title: data.title
|
||||
});
|
||||
data.create_at = friendlyDate((new Date(data.create_at.replace(/\-/g, '/')).getTime()))
|
||||
this.newsInfo = data;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
91
pages/tutorial/tutorial.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="flex flex-column flex-1">
|
||||
<scroll-view class="flex-1" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2">
|
||||
<i-tutorial-list :resdata="newsList" />
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
newsList: [],
|
||||
curPage: 1,
|
||||
loading: true,
|
||||
refresh: true,
|
||||
finish: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.newsList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get('/cms/api.tutorial/index', {
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.data.map((news) => {
|
||||
news.publish_at = friendlyDate(new Date(news.create_at.replace(/\-/g, '/'))
|
||||
.getTime())
|
||||
news.imgs = [];
|
||||
return news;
|
||||
});
|
||||
if (this.refresh) {
|
||||
this.newsList.length = 0;
|
||||
}
|
||||
this.newsList = this.newsList.concat(data_list);
|
||||
this.finish = data.total <= this.newsList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.newsList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
83
pages/user-share/detail.vue
Normal file
@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh;">
|
||||
<i-loading v-if="loading"></i-loading>
|
||||
<view class="bg-white px-3 pb-3 mx-2 rounded-lg mt-2">
|
||||
<view class="pt-3 font30">
|
||||
<view class="text-muted">反馈内容</view>
|
||||
<view class="mt-2">{{info.content}}</view>
|
||||
</view>
|
||||
<view class="pt-3 font30">
|
||||
<view class="text-muted">反馈地址</view>
|
||||
<view class="mt-2">{{info.ticket_region}} {{info.ticket_address}}</view>
|
||||
</view>
|
||||
<view class="flex align-center justify-between pt-3 font30">
|
||||
<view class="text-muted">反馈地址</view>
|
||||
<view>{{info.create_at}}</view>
|
||||
</view>
|
||||
<view class="pt-3 font30" v-if="info.imgs_arr.length > 0">
|
||||
<view class="text-muted">图片</view>
|
||||
<view class="mt-2">
|
||||
<image v-for="(item, index) in info.imgs_arr" :key="index" :src="item" mode="aspectFill" class="rounded-lg" style="width: 100px;height: 100px;margin-right: 10px;" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="info.status == 1" class="bg-white px-3 pb-3 mx-2 rounded-lg mt-2">
|
||||
<view class="pt-3 font30">
|
||||
<view class="text-muted">处理记录</view>
|
||||
<view class="mt-2">
|
||||
<view v-for="(item, index) in info.logs" :key="index" class="flex flex-column justify-between border-bottom border-light py-2">
|
||||
<view>处理时间:{{item.create_at}}</view>
|
||||
<view>{{item.content}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax'
|
||||
|
||||
export default {
|
||||
onLoad(options) {
|
||||
console.log(options)
|
||||
this.id = options.id
|
||||
if (!this.id) {
|
||||
uni.showToast({
|
||||
title: '缺少参数',
|
||||
icon: 'none'
|
||||
})
|
||||
return uni.navigateBack()
|
||||
}
|
||||
this.loadInfo()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: 0,
|
||||
loading: false,
|
||||
info: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadInfo() {
|
||||
this.loading = true
|
||||
TaAjax.get('/ticket/api.auth.UserShare/info?id=' + this.id).then(res => {
|
||||
console.log(res)
|
||||
this.info = res.data
|
||||
}).catch(err => {
|
||||
uni.showToast({
|
||||
title: err.info,
|
||||
icon: 'error',
|
||||
})
|
||||
uni.navigateBack()
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
205
pages/user-share/user-share.vue
Normal file
@ -0,0 +1,205 @@
|
||||
<template>
|
||||
<view class="flex flex-column" style="width:100vw;height: 100vh; background-color: #F5F6F8;">
|
||||
<view class="flex flex-row align-center px-2 py-1" style="background-color: #FFF8D3; height: 56rpx;">
|
||||
<image src="@/static/images/icon-warn.png" style="height: 24rpx; width: 24rpx;"></image>
|
||||
<text style="color: #FFBE0E; font-size: 20rpx">随手拍简单、高效的反馈并上传问题</text>
|
||||
</view>
|
||||
<view class="bg-white mt-2 p-2 rounded-lg" style="padding-bottom: 200rpx;">
|
||||
<view class="flex-1" style="color: #666666;">问题类型:</view>
|
||||
<picker class="border-bottom border-light" :range="typeList" range-key="name" @change="handleTypeIdChange">
|
||||
<view class="py-3 flex align-center justify-between">
|
||||
<view class=" font28 flex align-center flex-1" v-if="type_name">{{type_name}}
|
||||
</view>
|
||||
<view class=" font28 text-light-black flex-1" v-else>请选择问题分类</view>
|
||||
<uni-icons type="right" color="#cccccc" size="20"></uni-icons>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="flex-1 pt-3" style="color: #666666;">反馈内容:</view>
|
||||
<view class="border border-light rounded py-3 flex align-center justify-between" style="height: 200rpx;">
|
||||
<textarea v-model="form.content" autoHeight class="flex-1 font28" placeholder="随手拍反馈内容" />
|
||||
</view>
|
||||
<view class="flex-1 pt-3">问题地址:</view>
|
||||
<pick-regions defaultRegion="511602" @getRegion="handleGetRegion">
|
||||
<view class="py-3 flex align-center justify-between">
|
||||
<view class=" font28 flex align-center flex-1" v-if="province">{{province}}{{city}}{{area}}</view>
|
||||
<view class=" font28 text-light-black flex-1" v-else>省市区</view>
|
||||
<uni-icons type="right" color="#cccccc" size="20"></uni-icons>
|
||||
</view>
|
||||
</pick-regions>
|
||||
<view class="border rounded border-light py-3 flex align-center justify-between">
|
||||
<textarea v-model="form.ticket_address" autoHeight class="flex-1 font28" placeholder="详细地址(例如**街**号**)" />
|
||||
</view>
|
||||
<view class="flex-1 py-3">联系方式:</view>
|
||||
<view class="flex align-center justify-between py-3 ">
|
||||
<view class="flex-1 border-bottom border-light">
|
||||
<input class="font28" focus placeholder="姓名" v-model="form.contact_name" />
|
||||
</view>
|
||||
<view class="flex-1 border-bottom border-light">
|
||||
<input class="font28" type="number" placeholder="联系方式" v-model="form.contact_phone" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-1 py-3">相关图片:</view>
|
||||
<view class="flex py-3 mb-6">
|
||||
<div class="flex flex-wrap w-25 position-relative" v-for="(item,index) in img_array" :key='index'>
|
||||
<img class="img-add" :src="item" @click="previewImage(index)" alt=""/>
|
||||
<img class='img-delete position-absolute' src='/static/images/delete.png' @click='deleteImage(index)'>
|
||||
</div>
|
||||
<div class="flex flex-wrap w-25" @click="chooseImages()">
|
||||
<img class='img-add' src="/static/images/addImage.png" alt="">
|
||||
</div>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fixed-bottom border-top bg-white py-2 px-3">
|
||||
<view class="bg-danger py-3 font30 text-center text-white shadow rounded-circle" @click="onSubmit">
|
||||
立即提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaCache } from '../../common/cache';
|
||||
import {
|
||||
TaAjax, TaPost, baseUrl
|
||||
} from '@/common/ajax';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
province: "四川省",
|
||||
city: "广安市",
|
||||
area: "广安区",
|
||||
type_name: "",
|
||||
form: {
|
||||
type_id: 0,
|
||||
title: "用户随手拍",
|
||||
content: "",
|
||||
contact_name: "",
|
||||
contact_phone: "",
|
||||
ticket_region: "四川省/广安市/广安区",
|
||||
ticket_address: "",
|
||||
imgs: "",
|
||||
ticket_lat: null,
|
||||
ticket_lng: null,
|
||||
},
|
||||
img_array: [],
|
||||
typeList: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const that = this;
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (!userInfo) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
}
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
success(res) {
|
||||
that.form.ticket_lat = res.latitude;
|
||||
that.form.ticket_lng = res.longitude;
|
||||
},
|
||||
fail(err) {
|
||||
console.warn(err)
|
||||
}
|
||||
})
|
||||
},
|
||||
onReady() {
|
||||
this.getTypeList()
|
||||
},
|
||||
methods: {
|
||||
getTypeList() {
|
||||
TaAjax.get('/ticket/api.type/list').then((result) => {
|
||||
const data = result.data;
|
||||
this.typeList = data;
|
||||
})
|
||||
},
|
||||
handleTypeIdChange(e) {
|
||||
const index = e.detail.value;
|
||||
const curType = this.typeList[index];
|
||||
this.type_name = curType.name;
|
||||
this.form.type_id = curType.id
|
||||
},
|
||||
handleGetRegion(region) {
|
||||
this.province = region[0].name
|
||||
this.city = region[1].name
|
||||
this.area = region[2].name
|
||||
this.form.ticket_region = `${this.province}/${this.city}/${this.area}`
|
||||
},
|
||||
chooseImages() {
|
||||
const that = this;
|
||||
uni.chooseMedia({
|
||||
mediaType: ['image', 'video'],
|
||||
sourceType: ['album', 'camera'],
|
||||
sizeType: ['original'],
|
||||
success(res) {
|
||||
for(let i=0;i<res.tempFiles.length;i++){
|
||||
const tempFilePath = res.tempFiles[i].tempFilePath
|
||||
const loadingId = uni.showLoading({
|
||||
title: '上传中...',
|
||||
mask: true,
|
||||
})
|
||||
uni.uploadFile({
|
||||
url: baseUrl + '/custom/api.Upload/file',
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
success(res) {
|
||||
const responseStr = res.data;
|
||||
const response = JSON.parse(res.data);
|
||||
const data = response.data;
|
||||
const url = data.url;
|
||||
that.img_array.push(url);
|
||||
},
|
||||
complete() {
|
||||
uni.hideLoading(loadingId)
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
previewImage(idx = 0) {
|
||||
uni.previewImage({
|
||||
urls: this.img_array,
|
||||
current: idx,
|
||||
loop: true,
|
||||
})
|
||||
},
|
||||
deleteImage(idx) {
|
||||
this.img_array.splice(idx, 1)
|
||||
},
|
||||
onSubmit() {
|
||||
this.form.imgs = this.img_array.join("|")
|
||||
TaPost('/ticket/api.auth.UserShare/add', this.form).then((result) => {
|
||||
if (result.code == 0) {
|
||||
return uni.showToast({
|
||||
icon: 'error',
|
||||
title: result.info,
|
||||
})
|
||||
}
|
||||
const id = result.data
|
||||
uni.switchTab({
|
||||
url: "/pages/index/index"
|
||||
})
|
||||
return uni.showToast({
|
||||
icon: 'success',
|
||||
title: result.info,
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.img-add {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
}
|
||||
.img-delete {
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 48rpx;
|
||||
width: 48rpx;
|
||||
}
|
||||
</style>
|
63
pages/user/address.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<view class="px-2">
|
||||
<i-loading v-if="loading"></i-loading>
|
||||
<i-address-list :resdata="list" @click="toShow" @delete="doDelete" />
|
||||
<button @click="addAddress" class="fixed-bottom">添加地址</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
order_no: '',
|
||||
loading: false,
|
||||
list:[]
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.order_no = e.order_no
|
||||
},
|
||||
onShow() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
this.loading = true
|
||||
TaAjax.get('/points_mall/api.auth.address/list').then((resp) => {
|
||||
const data = resp.data;
|
||||
this.list = data
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
addAddress(e) {
|
||||
uni.navigateTo({
|
||||
url:'/pages/user/address_edit'
|
||||
})
|
||||
},
|
||||
toShow(item){
|
||||
if (this.order_no) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/points-mall/buy?order_no=' + this.order_no + '&address_id=' + item.id
|
||||
})
|
||||
} else {
|
||||
uni.navigateBack()
|
||||
}
|
||||
},
|
||||
doDelete(item) {
|
||||
TaAjax.post('/points_mall/api.auth.address/delete', {
|
||||
id: item.id,
|
||||
}).then((resp) => {
|
||||
this.loadData()
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
141
pages/user/address_edit.vue
Normal file
@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<view class="mx-2">
|
||||
<view class="bg-white rounded-lg p-3 mt-3">
|
||||
<view class="flex align-center justify-between border-bottom border-light py-3">
|
||||
<view class="flex-1">
|
||||
<input class="font28" focus placeholder="姓名" v-model="userName" />
|
||||
</view>
|
||||
<view class="flex-1">
|
||||
<input class="font28" type="number" placeholder="联系方式" v-model="tel" />
|
||||
</view>
|
||||
</view>
|
||||
<pick-regions :defaultRegion="defaultRegionCode" @getRegion="handleGetRegion">
|
||||
<view class=" border-bottom border-light py-3 flex align-center justify-between">
|
||||
<view class=" font28 flex align-center flex-1" v-if="province">{{province}}{{city}}{{district}}
|
||||
</view>
|
||||
<view class=" font28 text-light-black flex-1" v-else>省市区</view>
|
||||
<uni-icons type="right" color="#cccccc" size="20"></uni-icons>
|
||||
</view>
|
||||
</pick-regions>
|
||||
<view class=" border-bottom border-light py-3 flex align-center justify-between">
|
||||
<textarea v-model="address" autoHeight class="flex-1 font28" placeholder="详细地址(例如**街**号**)" />
|
||||
</view>
|
||||
<view class="flex align-center justify-between">
|
||||
<view class="flex align-center justify-between mt-2" @click="clear">
|
||||
<uni-icons type="trash-filled" size="16" color="#cccccc"></uni-icons>
|
||||
<text class="font24 ml-1 text-muted">清空当前信息</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fixed-bottom border-top bg-white py-2 px-3">
|
||||
<view class="bg-danger py-3 font30 text-center text-white shadow rounded-circle" @click="toList">立即保存
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="message" type="message">
|
||||
<uni-popup-message :type="msgType" :message="messageText" :duration="2000"></uni-popup-message>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '../../common/ajax'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
id: "",
|
||||
province: null,
|
||||
city: null,
|
||||
district: null,
|
||||
address: null,
|
||||
userName: null,
|
||||
tel: null,
|
||||
// 弹出验证信息
|
||||
message: null,
|
||||
msgType: null,
|
||||
messageText: null,
|
||||
region: [],
|
||||
defaultRegionCode: '110101'
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.id = options.id || ""
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 获取选择的地区
|
||||
handleGetRegion(region) {
|
||||
this.region = region
|
||||
this.province = region[0].name
|
||||
this.city = region[1].name
|
||||
this.district = region[2].name
|
||||
},
|
||||
toList() {
|
||||
if (this.userName == null || this.userName == '') {
|
||||
this.msgType = "error"
|
||||
this.messageText = `请输入联系人姓名`
|
||||
this.$refs.message.open()
|
||||
return
|
||||
}
|
||||
if (this.tel == null || this.tel == '') {
|
||||
this.msgType = "error"
|
||||
this.messageText = `请输入联系人手机号`
|
||||
this.$refs.message.open()
|
||||
return
|
||||
}
|
||||
if (!/^1[3456789]\d{9}$/.test(this.tel)) {
|
||||
this.msgType = "error"
|
||||
this.messageText = `请输入正确手机号`
|
||||
this.$refs.message.open()
|
||||
return
|
||||
}
|
||||
if (this.province == null || this.province == '') {
|
||||
this.msgType = "error"
|
||||
this.messageText = `请选择地址`
|
||||
this.$refs.message.open()
|
||||
return
|
||||
}
|
||||
const item = {
|
||||
id: this.id,
|
||||
user_name: this.userName,
|
||||
user_phone: this.tel,
|
||||
region_prov: this.province,
|
||||
region_city: this.city,
|
||||
region_area: this.district,
|
||||
region_addr: this.address,
|
||||
}
|
||||
TaAjax.post("/points_mall/api.auth.address/save", item).then((res) => {
|
||||
if (res.code == 1) {
|
||||
this.msgType = "success"
|
||||
this.messageText = `保存成功`
|
||||
this.$refs.message.open()
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 1000)
|
||||
} else {
|
||||
this.msgType = "error"
|
||||
this.messageText = `保存失败`
|
||||
this.$refs.message.open()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.address = '',
|
||||
this.companyName = '',
|
||||
this.userName = '',
|
||||
this.tel = '',
|
||||
this.province = '',
|
||||
this.city = '',
|
||||
this.district = ''
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
150
pages/user/bind/bind.vue
Normal file
@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<view class="flex flex-column">
|
||||
<view class="center-list">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">绑定手机</text>
|
||||
<input class="list-input" v-model="form.phone">
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">手机验证码</text>
|
||||
<view class="flex">
|
||||
<input type="nickname" class="list-input" v-model="form.verify">
|
||||
<button class="list-btn" :disabled="waiting" @click="getVerify">{{waiting ? `重新获取(${waitingTime}s)` : '获取验证码'}}</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="margin-top:80rpx;" class="flex-center">
|
||||
<button type="success" size="large" @click="doBind" customStyle="width:600rpx;height:100rpx">绑定</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax, TaPost } from '../../../common/ajax';
|
||||
import { TaCache } from '../../../common/cache';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
phone: '',
|
||||
verify: ''
|
||||
},
|
||||
waiting: false,
|
||||
waitingTime: 60
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getVerify() {
|
||||
TaAjax.post('/cms/api.auth.Bind/send', {
|
||||
phone: this.form.phone
|
||||
}).then(res => {
|
||||
uni.showToast({
|
||||
title: res.info,
|
||||
icon: 'success',
|
||||
})
|
||||
this.form.verify = "123456"
|
||||
this.waiting = true;
|
||||
this.waitingTime = 60;
|
||||
this.timer = setInterval(() => {
|
||||
this.waitingTime--;
|
||||
if (this.waitingTime <= 0) {
|
||||
this.waiting = false;
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
}, 1000)
|
||||
}).catch(err => {
|
||||
uni.showToast({
|
||||
title: "网络异常",
|
||||
icon: 'none',
|
||||
})
|
||||
})
|
||||
},
|
||||
doBind() {
|
||||
TaPost("/plugin-account/api.auth.center/bind", this.form).then((ret) => {
|
||||
if (ret.code === 1) {
|
||||
TaCache.set('auth.user', ret.data)
|
||||
uni.showToast({
|
||||
title: '绑定成功',
|
||||
icon: 'success',
|
||||
})
|
||||
uni.navigateBack()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.info,
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
uni.showToast({
|
||||
title: "网络异常",
|
||||
icon: 'none',
|
||||
})
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.go-login-navigat-arrow {
|
||||
font-size: 38upx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
height: 150upx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 20upx;
|
||||
}
|
||||
|
||||
.center-list {
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
margin-top: 20upx;
|
||||
width: 690upx;
|
||||
margin-left: 30upx;
|
||||
margin-right: 30upx;
|
||||
}
|
||||
|
||||
.center-list-item {
|
||||
height: 90upx;
|
||||
width: 690upx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0upx 20upx;
|
||||
border-radius: 10upx;
|
||||
box-shadow: #55555555 1rpx 0rpx 2rpx 0rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.list-text {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.list-text,.list-input {
|
||||
height: 90upx;
|
||||
line-height: 90upx;
|
||||
font-size: 34upx;
|
||||
color: #555;
|
||||
}
|
||||
.list-input {
|
||||
text-align: right;
|
||||
}
|
||||
.list-btn {
|
||||
font-size: 24rpx;
|
||||
flex-shrink: 0;
|
||||
height: 90upx;
|
||||
line-height: 90upx;
|
||||
}
|
||||
|
||||
</style>
|
203
pages/user/index.vue
Normal file
@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<view class="flex flex-column">
|
||||
<view class="logo" @click="goLogin" :hover-class="!isLogin ? 'logo-hover' : ''">
|
||||
<image class="logo-img" :src="isLogin ? userInfo.extra.avatarUrl : avatarUrl"></image>
|
||||
<view class="logo-title">
|
||||
<text class="user-name">Hi,{{userInfo.nickname || userInfo.extra.nickName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goUserInfo">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">账号管理</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goUserUserShare">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">我的随手拍</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goUserPoint">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">用户积分</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goUserOrder">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">我的订单</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goMessage">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">我的消息</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list" @click="goMorePage">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">更多设置</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaCache } from '@/common/cache'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
avatarUrl: '/static/images/user-no-avatar.png',
|
||||
isLogin: false,
|
||||
userInfo: {
|
||||
extra: {
|
||||
avatarUrl: '/static/images/user-no-avatar.png',
|
||||
nickname: '未登录',
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
this.isLogin = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goLogin() {
|
||||
if (!this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
}
|
||||
},
|
||||
goUserInfo() {
|
||||
if (!this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/info",
|
||||
})
|
||||
}
|
||||
},
|
||||
goUserPoint() {
|
||||
if (!this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/point"
|
||||
})
|
||||
}
|
||||
},
|
||||
goUserUserShare() {
|
||||
if (!this.isLogin) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/login"
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/user_share"
|
||||
})
|
||||
}
|
||||
},
|
||||
goMessage() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/message/message",
|
||||
})
|
||||
},
|
||||
goUserOrder() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/user/order",
|
||||
})
|
||||
},
|
||||
goMorePage() {
|
||||
uni.navigateTo({
|
||||
url: "/pages/const/more"
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 750upx;
|
||||
height: 240upx;
|
||||
padding: 20upx;
|
||||
background-color: #2F85FC;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
width: 150upx;
|
||||
height: 150upx;
|
||||
border-radius: 150upx;
|
||||
}
|
||||
|
||||
.logo-title {
|
||||
height: 150upx;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
margin-left: 20upx;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
height: 60upx;
|
||||
line-height: 60upx;
|
||||
font-size: 38upx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.go-login-navigat-arrow {
|
||||
font-size: 38upx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
height: 150upx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 20upx;
|
||||
}
|
||||
|
||||
.center-list {
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
margin-top: 20upx;
|
||||
width: 690upx;
|
||||
margin-left: 30upx;
|
||||
margin-right: 30upx;
|
||||
}
|
||||
|
||||
.center-list-item {
|
||||
height: 90upx;
|
||||
width: 690upx;
|
||||
flex-direction: row;
|
||||
padding: 0upx 20upx;
|
||||
border-radius: 10upx;
|
||||
box-shadow: #55555555 1rpx 0rpx 2rpx 0rpx;
|
||||
}
|
||||
|
||||
.list-text {
|
||||
height: 90upx;
|
||||
line-height: 90upx;
|
||||
font-size: 34upx;
|
||||
color: #555;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
</style>
|
157
pages/user/info.vue
Normal file
@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<view class="flex flex-column">
|
||||
<view class="center-list">
|
||||
<view class="center-list-item">
|
||||
<text class="list-text">账号昵称</text>
|
||||
<input type="nickname" class="list-input" v-model="form.nickname" @nicknamereview="changeName" @confirm="changeName">
|
||||
</view>
|
||||
</view>
|
||||
<view class="center-list">
|
||||
<view class="center-list-item" @click="setAvatar">
|
||||
<text class="list-text">修改头像</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax, TaPost, baseUrl } from '../../common/ajax';
|
||||
import { TaCache } from '../../common/cache';
|
||||
import { TaImageToBase64 } from '../../common/image';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userInfo: {},
|
||||
form: {
|
||||
nickname: "",
|
||||
}
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
const userInfo = TaCache.get('auth.user');
|
||||
if (userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
if (!this.userInfo.phone) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/bind'
|
||||
})
|
||||
}
|
||||
this.form.nickname = this.userInfo.nickname || this.userInfo.extra.nickName
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/login'
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeName() {
|
||||
uni.showLoading({
|
||||
title: "修改中..."
|
||||
})
|
||||
TaAjax.post('/plugin-account/api.auth.center/set', {
|
||||
nickname: this.form.nickname,
|
||||
extra: {
|
||||
nickName: this.form.nickname
|
||||
}
|
||||
}, {
|
||||
header: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(res => {
|
||||
uni.hideLoading();
|
||||
if (res.code == 1) {
|
||||
uni.showToast({
|
||||
title: "修改成功",
|
||||
icon: "success"
|
||||
})
|
||||
TaCache.set('auth.user', res.data);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
}).finally()
|
||||
},
|
||||
setAvatar() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sourceType: ['album'],
|
||||
success: (res) => {
|
||||
uni.showLoading({
|
||||
title: "上传中..."
|
||||
})
|
||||
uni.uploadFile({
|
||||
url: baseUrl + '/custom/api.Upload/file',
|
||||
filePath: res.tempFilePaths[0],
|
||||
name: 'file',
|
||||
success(res) {
|
||||
const responseStr = res.data;
|
||||
const response = JSON.parse(res.data);
|
||||
const data = response.data;
|
||||
const url = data.url;
|
||||
TaPost('/plugin-account/api.auth.center/set', {
|
||||
headimg: url
|
||||
}).then().finally(() => uni.hideLoading())
|
||||
},
|
||||
complete() {
|
||||
uni.hideLoading()
|
||||
},
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.go-login-navigat-arrow {
|
||||
font-size: 38upx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.login-title {
|
||||
height: 150upx;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-left: 20upx;
|
||||
}
|
||||
|
||||
.center-list {
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
margin-top: 20upx;
|
||||
width: 690upx;
|
||||
margin-left: 30upx;
|
||||
margin-right: 30upx;
|
||||
}
|
||||
|
||||
.center-list-item {
|
||||
height: 90upx;
|
||||
width: 690upx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0upx 20upx;
|
||||
border-radius: 10upx;
|
||||
box-shadow: #55555555 1rpx 0rpx 2rpx 0rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.list-text,.list-input {
|
||||
height: 90upx;
|
||||
line-height: 90upx;
|
||||
font-size: 34upx;
|
||||
color: #555;
|
||||
}
|
||||
.list-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
</style>
|
101
pages/user/login.vue
Normal file
@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<view class="login">
|
||||
|
||||
<view class="login-head flex-y">
|
||||
<text class="login-head-h1">登录</text>
|
||||
</view>
|
||||
|
||||
<view class="login-body flex-y">
|
||||
|
||||
<view class="flex-center">
|
||||
<text class="login-body-name">微信授权</text>
|
||||
</view>
|
||||
|
||||
<view style="margin-top:80rpx;" class="flex-center">
|
||||
<button type="success" size="large" @click="doLogin" customStyle="width:600rpx;height:100rpx">登
|
||||
录</button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<!--
|
||||
<view class="login-foot">
|
||||
<view class='login-foot-agent flex-center'>
|
||||
<checkbox label="1" v-model="agent.value">同意协议</checkbox>
|
||||
<text @click="agent.show = true">《用户隐私协议》</text>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '@/common/ajax';
|
||||
import { TaCache } from '@/common/cache';
|
||||
import { TaToast } from '@/common/toast';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 用户协议
|
||||
agent: {
|
||||
show: false,
|
||||
value: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const userInfo = TaCache.get('auth.user')
|
||||
if (userInfo) {
|
||||
uni.navigateBack()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 执行注册登录
|
||||
doLogin() {
|
||||
TaToast.loading("登录中")
|
||||
this.login().then((data) => {
|
||||
TaCache.set('auth.user', data)
|
||||
}).finally(() => {
|
||||
TaToast.loadhide()
|
||||
})
|
||||
},
|
||||
login() {
|
||||
return new Promise((resolve, reject) => uni.login({
|
||||
provider: 'weixin',
|
||||
success(loginRes) {
|
||||
// 换取会话密钥
|
||||
let data = {
|
||||
code: loginRes.code,
|
||||
iv: '',
|
||||
encrypted: ''
|
||||
}
|
||||
TaAjax.post('/plugin-account/api.wxapp/session', data).then((ret) => {
|
||||
console.log('SessionDone: ', ret)
|
||||
TaCache.set('auth.token', ret.data.token)
|
||||
// 获取用户信息
|
||||
uni.getUserInfo({
|
||||
provider: 'weixin',
|
||||
success: (infoRes) => {
|
||||
console.log('UserInfo: ', infoRes)
|
||||
data.iv = infoRes.iv, data.encrypted = infoRes
|
||||
.encryptedData
|
||||
TaAjax.post('/plugin-account/api.wxapp/decode', data)
|
||||
.then((ret) => {
|
||||
console.log('UserDone: ', ret.data)
|
||||
resolve(ret.data)
|
||||
}).catch((ret) => {
|
||||
console.log('UserFail: ', ret.data)
|
||||
reject(ret)
|
||||
})
|
||||
}
|
||||
})
|
||||
}).catch((ret) => {
|
||||
console.log('SessionFail: ', ret)
|
||||
reject(ret);
|
||||
})
|
||||
}
|
||||
}))
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
167
pages/user/order.vue
Normal file
@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<view class="flex flex-column overflow-hidden" style="height: 100vh;">
|
||||
<!-- <view class="flex align-center justify-between pt-3 bg-white flex-shrink">
|
||||
<view v-for="(item,index) in tabBar" :key="index" class="flex-1 text-center " @click="changeTab(index)">
|
||||
<text :class="tabIndex==index?'text-danger font-weight-bold':'text-muted'">{{item}}</text>
|
||||
<view :class="tabIndex==index?'bg-danger':''" style="width: 30rpx;height: 10rpx;" class="rounded-lg d-block mx-auto mt-2 "></view>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="flex-1" style="overflow-y: auto;">
|
||||
<scroll-view class="flex-1 list overflow-hidden" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData()" @scrolltolower="loadData()">
|
||||
<i-order-list :resdata="orderList" @cancel="cancelOrder" @confirm="confirmOrder"></i-order-list>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- <swiper class="flex-1" :current="tabIndex" @change="swiperChange" > -->
|
||||
<!-- <swiper-item class="flex" v-for="(item,index) in tabBar" :key="index"> -->
|
||||
|
||||
<!-- </swiper-item> -->
|
||||
<!-- </swiper> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TaAjax } from '../../common/ajax'
|
||||
import { friendlyDate } from '../../common/util';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tabIndex:0,
|
||||
tabBar:['全部','待发货','待收货','已收货'],
|
||||
loading: false,
|
||||
refresh: true,
|
||||
finish: true,
|
||||
curPage: 1,
|
||||
orderList: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
refreshData() {
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.orderList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
TaAjax.get('/points_mall/api.auth.order/get', {
|
||||
page: this.curPage
|
||||
}).then((response) => {
|
||||
const data = response.data;
|
||||
const data_list = data.list.map((item) => {
|
||||
item.create_at = friendlyDate(new Date(item.create_time.replace(/\-/g, '/'))
|
||||
.getTime())
|
||||
return item;
|
||||
})
|
||||
if (this.refresh) {
|
||||
this.orderList.length = 0
|
||||
}
|
||||
this.orderList = this.orderList.concat(data_list)
|
||||
this.finish = data.page.total <= this.orderList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.orderList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
changeTab(index){
|
||||
this.tabIndex = index
|
||||
this.refreshData()
|
||||
},
|
||||
swiperChange(e){
|
||||
this.tabIndex = e.detail.current
|
||||
this.refreshData()
|
||||
},
|
||||
cancelOrder(orderNo) {
|
||||
uni.showLoading({
|
||||
title: '取消中'
|
||||
})
|
||||
TaAjax.post('/points_mall/api.auth.order/cancel', {
|
||||
order_no: orderNo,
|
||||
}).then((response) => {
|
||||
if (response.code == 1) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '取消成功',
|
||||
icon: 'success',
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: response.info,
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '取消失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}).finally(() => {
|
||||
this.refreshData()
|
||||
})
|
||||
},
|
||||
confirmOrder(orderNo) {
|
||||
uni.showLoading({
|
||||
title: '确认中',
|
||||
})
|
||||
TaAjax.post('/points_mall/api.auth.order/confirm', {
|
||||
order_no: orderNo,
|
||||
}).then((response) => {
|
||||
if (response.code == 1) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '确认成功',
|
||||
icon: 'success',
|
||||
})
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: response.info,
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '确认失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}).finally(() => {
|
||||
this.refreshData()
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
143
pages/user/point.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view class="flex flex-column flex-1" style="height: 100vh;">
|
||||
<view class="flex logo">
|
||||
<view class="flex flex-1 flex-column center logo-title">
|
||||
<text class="text-center title title-huge">{{point}}</text>
|
||||
<text class="text-center title">当前积分</text>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="flex-1 list" :scroll-y="true" :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshLog" @scrolltolower="getLog">
|
||||
<uni-list class="flex flex-column flex-1">
|
||||
<uni-list-item v-for="(item, index) in logList" :key="index">
|
||||
<template v-slot:body>
|
||||
<view class="flex flex-1 flex-column">
|
||||
<text style="font-size: 36rpx;">{{item.reason}}</text>
|
||||
<text style="font-size: 24rpx; color: gray;">{{item.create_at}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<view class="flex align-center justify-center">
|
||||
<text>{{item.point>0?'+':''}}{{item.point}}</text>
|
||||
</view>
|
||||
</template>
|
||||
</uni-list-item>
|
||||
</uni-list>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="getLog"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
point: 0,
|
||||
logList: [],
|
||||
loading: false,
|
||||
refresh: false,
|
||||
finish: false,
|
||||
curPage: 1,
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.getPoint();
|
||||
this.getLog();
|
||||
},
|
||||
methods: {
|
||||
getPoint() {
|
||||
TaAjax.get('/points_mall/api.auth.UserPoint/myPoint').then((response) => {
|
||||
const data = response.data;
|
||||
this.point = data.point
|
||||
})
|
||||
},
|
||||
refreshLog() {
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.getPoint()
|
||||
this.getLog();
|
||||
},
|
||||
getLog() {
|
||||
if (this.refresh) {
|
||||
this.logList.length = 0
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get('/points_mall/api.auth.UserPoint/myPointLog', {
|
||||
page: this.curPage
|
||||
}).then((response) => {
|
||||
const data = response.data;
|
||||
const data_list = data.data.map((item) => {
|
||||
item.create_at = friendlyDate(new Date(item.create_at.replace(/\-/g, '/'))
|
||||
.getTime())
|
||||
return item;
|
||||
})
|
||||
if (this.refresh) {
|
||||
this.logList.length = 0
|
||||
}
|
||||
this.logList = this.logList.concat(data_list)
|
||||
this.finish = data.page.total <= this.logList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.logList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.logo {
|
||||
width: 750upx;
|
||||
height: 240upx;
|
||||
padding: 20upx;
|
||||
background-color: $uni-color-primary;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo-title {
|
||||
height: 150upx;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: white;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.title-huge {
|
||||
font-size: 72rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.list {
|
||||
height: calc(100vh - 240rpx);
|
||||
}
|
||||
</style>
|
91
pages/user/user_share.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<view class="flex flex-column flex-1" style="height: 100vh;">
|
||||
<i-loading v-if="loading" />
|
||||
<view class="flex flex-column flex-1" style="height: 100%;">
|
||||
<scroll-view class="flex-1 overflow-hidden" style="height: 100%;" scroll-y :refresher-enabled="true"
|
||||
:refresher-triggered="refresh" @refresherrefresh="refreshData" @scrolltolower="loadData">
|
||||
<view class="px-2 overflow-scroll">
|
||||
<i-user-share-list :resdata="shareList" />
|
||||
</view>
|
||||
<uni-load-more :status="more_status" @clickLoadMore="loadData"></uni-load-more>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
TaAjax
|
||||
} from '@/common/ajax';
|
||||
import {
|
||||
friendlyDate
|
||||
} from '@/common/util';
|
||||
export default {
|
||||
computed: {
|
||||
more_status() {
|
||||
if (this.finish) {
|
||||
return 'no-more';
|
||||
} else if (this.loading) {
|
||||
return 'loading';
|
||||
} else {
|
||||
return 'more';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shareList: [],
|
||||
curPage: 1,
|
||||
loading: true,
|
||||
refresh: true,
|
||||
finish: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
if (this.refresh) {
|
||||
this.shareList.length = 0;
|
||||
this.finish = false;
|
||||
}
|
||||
if (this.finish) {
|
||||
return;
|
||||
}
|
||||
TaAjax.get('/ticket/api.auth.UserShare/index', {
|
||||
page: this.curPage
|
||||
}).then((result) => {
|
||||
const data = result.data;
|
||||
const data_list = data.data.map((share) => {
|
||||
share.create_at = friendlyDate(new Date(share.create_at.replace(/\-/g, '/'))
|
||||
.getTime());
|
||||
share.imgs = share.imgs_arr;
|
||||
return share;
|
||||
});
|
||||
if (this.refresh) {
|
||||
this.shareList.length = 0;
|
||||
}
|
||||
this.shareList = this.shareList.concat(data_list);
|
||||
this.finish = data.total <= this.shareList.length;
|
||||
this.curPage++;
|
||||
}).catch((e) => {
|
||||
console.warn(e)
|
||||
if (this.shareList.length == 0) {
|
||||
this.finish = true;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.refresh = false;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
refreshData() {
|
||||
this.finish = false;
|
||||
this.refresh = true;
|
||||
this.curPage = 1;
|
||||
this.loadData();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
BIN
static/images/addImage.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
static/images/delete.png
Normal file
After Width: | Height: | Size: 842 B |
BIN
static/images/icon-bszn-n.png
Normal file
After Width: | Height: | Size: 950 B |
BIN
static/images/icon-bszn.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/icon-city.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
static/images/icon-dzcs-n.png
Normal file
After Width: | Height: | Size: 736 B |
BIN
static/images/icon-dzcs.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/images/icon-guide.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
static/images/icon-home-n.png
Normal file
After Width: | Height: | Size: 945 B |
BIN
static/images/icon-home.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/icon-like.png
Normal file
After Width: | Height: | Size: 439 B |
BIN
static/images/icon-mall-n.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
static/images/icon-mall.png
Normal file
After Width: | Height: | Size: 1.6 KiB |