Commit f9e63e33 by huahua

提交

parent c953650d

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"h5" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}
<script>
import logoservice from '@/service/logoservice.js';
export default {
globalData: {
bindWx: null, //判断有没有用户之前登录过
machine_id: null, //设备id
},
methods: {
//调转登录选择页面判断
toPageLogin(promoter_id) {
try { //数据缓存 同步 一定要用try catch 包裹
uni.setStorageSync('promoter_id', promoter_id);
} catch (e) {
};
if (promoter_id != "" && promoter_id != "null") {
uni.reLaunch({
url: '/pages/login/select_login?machine_id=' + this.globalData.machine_id +
'&language=' + this._i18n.locale + "&promoter_id=" +
promoter_id //+ "&isLoadComplete=true"
});
} else {
uni.reLaunch({
url: '/pages/login/select_login?machine_id=' + this.globalData.machine_id +
'&language=' + this._i18n.locale //+ "&isLoadComplete=true"
});
}
},
//设置语言
saveLanguage(defaultStr) {
this._i18n.locale = 'en-us';
uni.setStorageSync('lang', this._i18n.locale);
switch (defaultStr) {
case "ch":
case "zh-cn":
this._i18n.locale = 'zh-cn';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "zh":
case "en-us":
this._i18n.locale = 'en-us';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "it":
case "it-it":
this._i18n.locale = 'it-it';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "tc":
case "zh-tc":
this._i18n.locale = 'zh-tc';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "ja-ja":
this._i18n.locale = 'ja-ja';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "fr-fr":
this._i18n.locale = 'fr-fr';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "de-de":
this._i18n.locale = 'de-de';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "po-po":
this._i18n.locale = 'po-po';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "es-es":
this._i18n.locale = 'es-es';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "dm-dm":
this._i18n.locale = 'dm-dm';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "ko-ko":
this._i18n.locale = 'ko-ko';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "pl-pl":
this._i18n.locale = 'pl-pl';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "ru-ru":
this._i18n.locale = 'ru-ru';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "ar-ar": //ar-ar-阿拉伯语语
this._i18n.locale = 'ar-ar';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "bd-bd": //bd-bd-孟家加拉
this._i18n.locale = 'bd-bd';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "fl-fl": //fl-fl-芬兰语
this._i18n.locale = 'fl-fl';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "hun-hun": //hun-hun-匈牙利语
this._i18n.locale = 'hun-hun';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "nl-nl": //nl-nl-荷兰语
this._i18n.locale = 'nl-nl';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "th-th": //th-th-泰语
this._i18n.locale = 'th-th';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "tur-tur": //tur-tur-土耳其语
this._i18n.locale = 'tur-tur';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "ua-ua": //ua-ua-乌克兰语
this._i18n.locale = 'ua-ua';
uni.setStorageSync('lang', this._i18n.locale);
break;
case "vn-vn": //vn-vn-越南语
this._i18n.locale = 'vn-vn';
uni.setStorageSync('lang', this._i18n.locale);
break;
}
},
},
onLaunch: function(options) {
//console.log('App Launch')
//this.$base.countFirst = this.$base.countFirst + 1;
//console.log(this.$base.countFirst);
this.$base.countFirst = 0;
try {
const value = uni.getStorageSync('globalData');
if (value) {
this.globalData = value
}
} catch (e) {
};
let promoter_id = "";
if (options.query.promoter_id && options.query.promoter_id != "null" && options.query.promoter_id !=
"") { //判断推广Id
promoter_id = options.query.promoter_id
}
let lang = uni.getStorageSync('lang');
if (lang && lang != "" && lang != null) {
this._i18n.locale = lang;
this.saveLanguage(this._i18n.locale);
}
if (options.query.machine_id && options.query.machine_id != "null") { //判断传的有没有设备id
this.globalData.machine_id = options.query.machine_id
try { //数据缓存 同步 一定要用try catch 包裹
uni.setStorageSync('machine_id', this.globalData.machine_id);
} catch (e) {
//TODO handle the exception
};
if (lang && lang != "" && lang != null) {
this._i18n.locale = lang;
this.saveLanguage(this._i18n.locale);
} else {
this.saveLanguage('en-us');
logoservice.verifyToken({
machine_id: options.query.machine_id,
s: 'MachineLanguage.getLanguageList'
}).then(res => {
let defaultStr = res.default
this.saveLanguage(defaultStr);
}).catch(err => {
this.saveLanguage('en-us');
});
}
} else {
let hrefStr = window.location.href;
if (hrefStr.indexOf("mine/pay_paypal") != -1 ||
hrefStr.indexOf("mine/pay_success") != -1 ||
hrefStr.indexOf("mine/pay_fail") != -1 ||
hrefStr.indexOf("mine/orderDetail") != -1 ||
hrefStr.indexOf("login/login") != -1 ||
hrefStr.indexOf("login/select_login") != -1
) {} else {
uni.reLaunch({
url: '/pages/index/mall',
});
return;
}
}
try { //数据缓存 同步 一定要用try catch 包裹
if (this.globalData != null) {
uni.setStorageSync('globalData', this.globalData);
}
} catch (e) {
};
var bindWx = null;
try {
bindWx = uni.getStorageSync('bindWx');
} catch (e) {
};
if (this.globalData.bindWx || bindWx) { //判断有没有用户之前登录过
logoservice.verifyToken({
s: 'User.verifyToken'
}).then(result => {
//console.log(result);
/*uni.reLaunch({
url: '/pages/login/select_login?machine_id=' + this.globalData.machine_id +'&language=' + this._i18n.locale
});*/
}).catch(err => {
if (promoter_id != "" && promoter_id != "null") {
} else {
promoter_id = ""
}
this.toPageLogin(promoter_id);
})
} else {
if (promoter_id != "" && promoter_id != "null") {
} else {
promoter_id = ""
}
this.toPageLogin(promoter_id);
}
},
onShow: function() {
//调用监听网络状态的方法
uni.getNetworkType({
success: function(res) {
if (res.networkType == 'none') {
uni.showToast({
title: '网络似乎不太顺畅',
icon: 'none',
duration: 2000
});
}
}
})
},
onHide: function() {
},
onLoad: function(options) {
}
}
</script>
<style>
/* uni.css - 通用组件、模板样式库,可以当作一套ui库应用 */
@import './common/uni.css';
/*每个页面公共css */
image {
object-fit: cover;
}
.hover-class-bg {
background: #888888 !important;
}
.hover-class-text {
color: #888888 !important;
}
</style>
import request from '../util/request'
import $n from '../util/nothing'
import Enums from '../util/Enums'
import Qs from 'qs'
/**
* ajax请求
* @param {*}
*/
export function _request ({
url,
params = {},
method = 'post',
token = false,
timeout = false,
contentType = Enums.ContentType.JSON_UTF8,
headers = {}
} = {}) {
headers['Content-Type'] = contentType;
return request.request(url, $n._caseValue(contentType, Enums.ContentType.FORM_UTF8, Qs.stringify(params), params), {
method: method,
_token: token,
_timeout: timeout,
headers
})
}
/**
* 分页查询
* @param {*}
*/
export function _queryPage ({
url,
params = {},
page = {},
method = 'post',
token = false,
contentType = Enums.ContentType.JSON_UTF8
} = {}) {
return _request({
url,
params,
method,
token,
contentType,
headers: {
'pageNum': page.pageNum,
'pageSize': page.pageSize
}
})
}
/**
* 流式分页查询
* @param {*}
*/
export function _queryFlowPage ({
url,
params = {},
page = {},
method = 'post',
token = false,
contentType = Enums.ContentType.JSON_UTF8
} = {}) {
return _request({
url,
params,
method,
token,
contentType,
headers: {
'beginTime': page.beginTime,
'direction': page.direction,
'orderBy': page.orderBy,
'pageSize': page.pageSize
}
})
}
import Enums from '../util/Enums'
import {
_request
} from './BaseApi'
/**
* 登录
* @param {*} params
*/
export const _login = (params = {}) => _request({url: '/zijie/index/register', params, method: 'post', contentType: Enums.ContentType.FORM_UTF8})
/**
* 查询用户信息
* @param {*} params
*/
// export const _queryUser = (id = null) => _request({url: '/member/info/' + id, params: {}, token: true, method: 'get'})
/**
* 刷新用户Token
* @param {*} params
*/
// export const _refreshToken = (oldToken = null) => _request({url: '/sso/refreshToken', params: {token: oldToken}, token: true, method: 'post'})
import Enums from '../util/Enums'
import {
_request
} from './BaseApi'
/**
* contentType: Enums.ContentType.FORM_UTF8
* 色彩公园手机壳/色彩公园T恤
* @param {*} params
*/
let T_URL = '/usertshirtsapplets/index'
let P_URL = '/userphoneapplets/index'
export const T_route = (params = {}) => _request({url: T_URL, params, method: 'post',token: true})
export const T_route_timeout = (params = {}) => _request({url: T_URL, params, method: 'post',token: true,timeout: true})
export const P_route = (params = {}) => _request({url: P_URL, params, method: 'post',token: true})
export const P_route_timeout = (params = {}) => _request({url: P_URL, params, method: 'post',token: true,timeout: true})
// 色彩公园
export const C_route = (params = {}) => _request({url: '/userapplets/index', params, method: 'post',token: true})
export const _utfgetShotBankCode = (params = {}) => _request({url: '/usertshirtsapplets/index', params, method: 'post',token: true})
export const paypal_success = (params = {}) => _request({url: '/api/Paypal/success', params, method: 'post',token: true})
export const paypal_cancel = (params = {}) => _request({url: '/api/Paypal/cancel', params, method: 'post',token: true})
export const _getOrderList = (params = {}) => _request({url: "/douyin/Order/getOrderList", params, token: true, method: 'post', contentType: Enums.ContentType.FORM_UTF8})
import Enums from '../util/Enums'
import {
_request
} from './BaseApi'
/**
* 初始化
* @param {*} params
*/
export const _userlogin = (params = {}) => _request({url: '/userphoneapplets/index', params, method: 'post',token: true, contentType: Enums.ContentType.FORM_UTF8})
export const _login = (params = {}) => _request({url: '/partnerapplets/index', params, method: 'post', contentType: Enums.ContentType.FORM_UTF8})
export const _shoplist = (params = {}) => _request({url: '/partnerapplets/index', params,token: true, method: 'post'})
/**
* 延迟
* @param {*} params
*/
export const route_timeout = (params = {}) => _request({url: '/partnerapplets/index', params, method: 'post',token: true,timeout: true})
\ No newline at end of file
export default {
app: {
APP_USER: 'APP_USER',
// app信息
WX_INFO: 'WX_INFO',
// 微信信息
USER_INFO: 'USER_INFO',
// 用户信息
DATA_SYNC_TIME: 'DATA_SYNC_TIME',
// 数据同步时间
BACKGROUND_COLOR: 'BACKGROUND_COLOR',
// 背景色
NAVIGATION_BAR_BACKGROUND_COLOR: 'NAVIGATION_BAR_BACKGROUND_COLOR',
// 导航条背景颜色
NAVIGATION_BAR_FRONT_COLOR: 'NAVIGATION_BAR_FRONT_COLOR' // 导航条前景颜色
},
SEARCH: 'SEARCH',
// 搜索
DECIMALS: 'DECIMALS',
// 小数位数
DICT: 'DICT_' // 字典
};
\ No newline at end of file
import CacheKeys from './CacheKeys';
/**
* 本地存储KEY前缀
*/
const _KEY_PREFIX = 'HL_';
/**
* 用户级缓存定义
*/
const CACHE_LEVEL_USER = [];
/**
* 构造缓存KEY
* @param {*} key
*/
const buildKey = key => {
let newKey = _KEY_PREFIX;
newKey += CACHE_LEVEL_USER.indexOf(key) !== -1 ? (newKey.endsWith('_') ? '' : '_') + this.$AppContext.$store.getters.sysUser.username : '';
return newKey + (newKey.endsWith('_') ? '' : '_') + key;
};
/**
* 缓存对象API
*/
const cache = {
$Keys: CacheKeys,
_KEY_PREFIX: _KEY_PREFIX,
set: object => uni.setStorage(Object.assign(object, {
key: buildKey(object.key)
})),
get: object => uni.getStorage(Object.assign(object, {
key: buildKey(object.key)
})),
setSync: (key, data) => uni.setStorageSync(buildKey(key), data),
getSync: key => uni.getStorageSync(buildKey(key)),
remove: object => uni.removeStorage(Object.assign(object, {
key: buildKey(object.key)
})),
removeSync: key => uni.removeStorageSync(buildKey(key)),
clear: object => uni.clearStorage(object),
clearSync: () => uni.clearStorageSync(),
getInfo: object => uni.getStorageInfo(object),
getInfoSync: () => uni.getStorageInfoSync()
};
export default cache;
\ No newline at end of file
/**
数据验证(表单验证)
来自 grace.hcoder.net
作者 hcoder 深海
*/
module.exports = {
error:'',
check : function (data, rule){
for(var i = 0; i < rule.length; i++){
if (!rule[i].checkType){return true;}
if (!rule[i].name) {return true;}
if (!rule[i].errorMsg) {return true;}
if (!data[rule[i].name]) {this.error = rule[i].errorMsg; return false;}
switch (rule[i].checkType){
case 'string':
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
case 'int':
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
if(!reg.test(data[rule[i].name])) {this.error = rule[i].errorMsg; return false;}
break;
break;
case 'between':
if (!this.isNumber(data[rule[i].name])){
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenD':
var reg = /^-?[1-9][0-9]?$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenF':
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
if (!reg.test(data[rule[i].name])){this.error = rule[i].errorMsg; return false;}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'same':
if (data[rule[i].name] != rule[i].checkRule) { this.error = rule[i].errorMsg; return false;}
break;
case 'notsame':
if (data[rule[i].name] == rule[i].checkRule) { this.error = rule[i].errorMsg; return false; }
break;
case 'email':
var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'phoneno':
var reg = /^1[0-9]{10,10}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'zipcode':
var reg = /^[0-9]{6}$/;
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'reg':
var reg = new RegExp(rule[i].checkRule);
if (!reg.test(data[rule[i].name])) { this.error = rule[i].errorMsg; return false; }
break;
case 'in':
if(rule[i].checkRule.indexOf(data[rule[i].name]) == -1){
this.error = rule[i].errorMsg; return false;
}
break;
case 'notnull':
if(data[rule[i].name] == null || data[rule[i].name].length < 1){this.error = rule[i].errorMsg; return false;}
break;
}
}
return true;
},
isNumber : function (checkVal){
var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
return reg.test(checkVal);
}
}
\ No newline at end of file
//api接口定义
var URL = {
base:'http://39.106.164.101:80/tt/',
getsy:'getPostList.php',
detail:'getSinglePost.php',
publish:'publish.php',
comment:'comment.php',
dtdetail:'detail.php',
update_profile:'updateProfile.php',
homepage:'getsc.php',
fans:'fan.php',
blackList:'blackList.php',
delete_sc:'deletesc.php',
sh:'sh.php',
daren:'darenList.php',
login:'login.php',
register:'register.php',
get_checkcode:'sendCheckCode.php',
get_msglist:'message.php',
jubao:'jubao.php',
feedback:'feedback.php',
check_version:'checkUpdate.php',
//html
publish_note :'p/publishNotes.html',//发布须知
user_agreement : "p/userAgreement.html",
aboutus_url : "p/aboutus.html",
contactus : "p/contactus.html",
disclaimer : "p/disclaimer.html",
usehelp: "p/usehelp.html",
privacy_agreement:"p/userPrivacy.html",
feedbackList:"p/feedbackList.html",
joinus:"p/joinus.html"
}
//http://39.106.164.101:80/tt/p/feedbackList.html
//全局变量
var add_score_share = 2;//分享
var add_score_login = 1;//每日登陆
var dt_type_sy = 'sy';//动态类型
var dt_type_zt = 'zt';
var dt_type_life = 'life';
//根据type获取动态分类(首页、专题、生活)
function getItemCategory(type){
var _category = dt_type_life;
var _type = type;
switch (_type){
case '10':
case '11':
case '12':
case '13':
case '14':
case '15':
_category = dt_type_sy;break;
case '6':_category = dt_type_zt;break;
default:break;
}
return _category;
}
/**Post
* type:请求类型
* url:地址
* pars:参数
* success:成功回调
* error:失败回调
*/
function uniPost(url , pars , success , error){
uni.getNetworkType({
success: (res) => {
console.log("---netType: " + JSON.stringify(res));
// if(res.networkType == 'none')uni.showToast({title:'无法连接网络' , icon:"none"});
}
});
var _url = URL.base + url;
// var token , userJsonStr = localStorage.getItem("loginuserinfo");
// if(userJsonStr){
// var _u = JSON.parse(userJsonStr);
// if(_u && _u['token']){
// token = _u['token'];pars['t'] = token;
// if(pars['z'] != 1){//1不需要当前uid , 获取他人
// pars['uid'] = _u['user_id'];//UID和token一起为了验证用户合法性
// }
// // pars['z'] && delete pars.z;
// }
// }
uni.request({url:_url,method:"POST",
header:{"content-type":"application/x-www-form-urlencoded"},
dataType:"json",
data:pars,
success: res =>{
// console.log("====res: " + JSON.stringify(res));
var data = res.data;
if(data.status == 200) {
console.log("request ok");
success(data.body);
}else{
if(error)error(data['msg'] || '服务器返回错误');
}
},
fail: (data, code) => {
var err = '请求网络失败' + JSON.stringify(data);
console.log("post error: " + err)
if(error){error(err);}
}
});
}
/**
* @param {Object} url
* @param {Object} pars
* @param {Object} files
* @param {Object} success
* @param {Object} error
*/
function uniUploadFile(url , pars , files, success , error){
var igs = files.map((value, index) => {return {name: "files[" + index + ']',uri: value}});
//用户权限验证参数
//console.log("pars:" + JSON.stringify(pars));//return;
uni.uploadFile({
url: URL.base + url,
files: igs,
formData: pars,
success: (res) => {
var code = res.statusCode , dataStr = res.data;
var obj = JSON.parse(dataStr);
if(obj.status == 200 && code == 200) {
success(obj.body);
}else{
if(error)error(obj['msg'] || '服务器返回错误');
}
},
fail: (res) => {
if(error)error(res);return;
uni.showToast({ title: "请求网络失败!",icon:'none'});
}
});
}
module.exports = {
post:uniPost,
url:URL,
uploadfile:uniUploadFile,
postType:getItemCategory
}
/*
{
"data": {
"status": 200,
"msg": "ok",
"body": []
},
"statusCode": 200,
"header": {
"connection": "Keep-Alive",
"content-type": "application/json;charset=UTF-8",
"date": "Thu, 26 Sep 2019 07:09:18 GMT",
"keep-alive": "timeout=5, max=100",
"server": "Apache/2.4.6 (CentOS) PHP/5.6.31",
"transfer-encoding": "Identity",
"x-powered-by": "PHP/5.6.31"
},
"errMsg": "request:ok"
}
*/
\ No newline at end of file
/**
* 检测APP版本更新
*/
function appCheckUpdate () {
var d = {'_api_key':'ebe6e53b3237688c541d87544b55dfbc'};
if (mui.os.ios) {
d['appKey'] = 'e4baef4023fca4396c54c20e1199108e';
} else{
d['appKey'] = '0e082a5068be599f54f7919486ffab05';
}
var appid = plus.runtime.appid;
if(appid == 'HBuilder')return;
mui.post('https://www.pgyer.com/apiv2/app/check' , d , function(res){
if(!(res && res['data']))return;
var appdata = res['data'];
var newVersion = appdata['buildVersion'];
var url = appdata['downloadURL'];
var versDes = appdata['buildUpdateDescription'];
// console.log(JSON.stringify(res));
plus.runtime.getProperty(appid , function(info){
var appver = info['version'];
if (newVersion > appver) {
mui.confirm(versDes,'新版本(' + newVersion + ')' , ["下载更新", "取消"], function(e) {
if(e.index == 0){
//iOS - 4.3+ (支持): 不支持ipa包的安装,Android - 2.2+ (支持): 可支持apk包的安装
if(mui.os.ios){
window.location.href = url;//文件下载,任务栏弹框不会自动安装
}else{
_startDownloadTask(url);
}
//plus.runtime.openURL(url);
}
});
}
});
} , 'json');
}
/**
* @param {Object} url
* 下载安装app,仅适用于Android系统
*/
function _startDownloadTask(url){
// mui('#popover').popover('show');
// mui("#progress-bar").progressbar({progress:0}).show();
plus.nativeUI.showWaiting('APP更新中...');
var downloadTask = plus.downloader.createDownload(url , {} , function(download , status){
plus.nativeUI.closeWaiting();
// mui('#popover').popover('hide');
if(200 != status)return;
var _filename = download.filename;
//仅支持本地地址,调用此方法前需把安装包从网络地址或其他位置放置到运行时环境可以访问的本地目录。
plus.runtime.install(_filename, {}, function(){
//console.log('install ok:' + _filename);
/*此处执行删除有问题,apk未来得及安装已经被删除*/
// plus.io.resolveLocalFileSystemURL('_downloads/' , function(entry){
// console.log(entry);
//
// entry.removeRecursively(function(entrys){
// console.log(_filename + '删除成功');
// });
// });
}, function(err){
console.log(err);
});
});
downloadTask.addEventListener('statechanged' , function(download , status){
//console.log(download.downloadedSize / 1024.0 + '-' + download.totalSize / 1024.0);
var _has = 0.0;
if(download.totalSize > 0){
_has = download.downloadedSize / download.totalSize;
_has = Math.round(_has * 1000)/10;
// mui("#progress-bar").progressbar().setProgress(_has);
}
// mui('#download-progerss')[0].innerText = _has + '%';
});
downloadTask.start();
}
\ No newline at end of file
var homeTopItems = [
{
text:'热门',
image:'heme-top1.png',
type:1
},
{
text:'打听',
image:'heme-top2.png',
type:11
},
{
text:'吐槽',
image:'heme-top3.png',
type:12
},
{
text:'公告',
image:'heme-top4.png',
type:13
},
{
text:'商家',
image:'home-top-sj@2x.png',
type:14,
invaild:1
},
{
text:'相亲交友',
image:'home-top-jy@2x.png',
type:15,
invaild:1
},
{
text:'求职招聘',
image:'home-top-qz@2x.png',
type:16,
invaild:1
},{
text:'便民信息',
image:'home-top-more@2x.png',
type:17
}
];
///用于列表查询
var titleForType = {
'10':'新鲜事',
// '11':'活动',
'11':'打听',
'12':'吐槽',
'13':'公告',
'20':'吃喝玩乐',
'21':'求职招聘',
'22':'商家信息',
'23':'相亲交友',
'24':'房屋信息',
'25':'打车出行',
'26':'二手交易',
'27':'便民信息'
}
//首页列表可用的数据类型
var homeAvaliableItemType = ['10' , '11' , '12' , '13' , '14' , '15'];
//分类数据
var itemType = [
[
{
'id':'10',
'text':'新鲜事',
},
{
'id':'11',
'text':'打听',
},
{
'id':'12',
'text':'吐槽',
},
{
'id':'13',
'text':'公告',
}
],
[{
'id':'20',
'title':'吃喝玩乐',
},
{
'id':'21',
'title':'求职招聘',
},
{
'id':'22',
'title':'商家信息',
},
{
'id':'23',
'title':'相亲交友',
},
{
'id':'24',
'title':'房屋信息',
},
{
'id':'25',
'title':'打车出行',
},
{
'id':'26',
'title':'二手交易',
},
{
'id':'27',
'title':'便民信息',
}]
];
//发布类型
var itemType_new = [
[
[
{
'id':'10',
'text':'新鲜事',
},
{
'id':'11',
'text':'打听',
}
],
[
{
'id':'12',
'text':'吐槽',
},
{
'id':'13',
'text':'公告',
}
]
],
[
[
{
'id':'21',
'text':'求职招聘',
},
{
'id':'22',
'text':'商家信息',
},
],
[
{
'id':'23',
'text':'相亲交友',
},
{
'id':'27',
'text':'便民信息',
}
]
]
];
//动态审核状态
var itemStatus = {
'0':'待审核',
'1':'已通过',
'2':'未通过',
};
function postSubType(t1,t2){
var s ='';
switch (t1){
case '21': s = t2 == 1 ? '招聘' : '求职';break;
case '23': s = t2 == 1 ? '我是女生' : '我是男生';break;
case '24':s = t2 == 1 ? '我要找房' : '我是房主';break;
case '25':s = t2 == 1 ? '人找车' : '车找人';break;
default:break;
}
return s;
}
module.exports = {
titleForType:titleForType,
homeAvaliableItemType:homeAvaliableItemType,
itemType:itemType_new,
itemStatus:itemStatus,
homeTopItems:homeTopItems,
postSubType:postSubType
}
\ No newline at end of file
//时间戳转换成时间格式方法
function dateFromTimestamp(time , isfull) {
var date=new Date(parseInt(time));
var year=date.getFullYear();
var mon = date.getMonth()+1;
var day = date.getDate();
var hours = date.getHours();
var minu = date.getMinutes();
var sec = date.getSeconds();
if(isfull){
return year+'-'+_formatter(mon)+'-'+_formatter(day)+' '+_formatter(hours)+':'+_formatter(minu)+':'+_formatter(sec);
}
return _formatter(hours)+':'+_formatter(minu);
}
function _formatter(m){return m<10?'0'+m:m }
/**
* 格式化时间的辅助类,将一个时间转换成x小时前、y天前等
*/
var dateUtils = {
UNITS: {
'年': 31557600000,
'月': 2629800000,
'天': 86400000,
'小时': 3600000,
'分钟': 60000,
'秒': 1000
},
humanize: function(milliseconds) {
var humanize = '';
mui.each(this.UNITS, function(unit, value) {
if(milliseconds >= value) {
humanize = Math.floor(milliseconds / value) + unit + '前';
return false;
}
return true;
});
return humanize || '刚刚';
},
format: function(dateStr) {
var date = this.parse(dateStr)
var diff = Date.now() - date.getTime();
if(diff < this.UNITS['天']) {
return this.humanize(diff);
}
var _format = function(number) {
return(number < 10 ? ('0' + number) : number);
};
return date.getFullYear() + '-' + _format(date.getMonth() + 1) + '-' + _format(date.getDate());
// return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' + _format(date.getHours()) + ':' + _format(date.getMinutes());
},
parse: function(str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
var a = str.split(/[^0-9]/);
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
}
};
\ No newline at end of file
function hud_show(msg){
plus.nativeUI.showWaiting(msg);
}
function hud_close(msg){
plus.nativeUI.closeWaiting();
plus.nativeUI.toast(msg , {verticalAlign:'center'});
}
function hud_toast(msg){
plus.nativeUI.toast(msg , {verticalAlign:'center'});
}
\ No newline at end of file
/**
* url:页面地址
* title:导航栏标题
* displayNavigationBar:是否需要导航栏
* datasource:传递的参数
* navIsTransparent:导航栏是否透明
*/
function openNewPageWithTransparent( url , title , displayNavigationBar , datasource , navIsTransparent){
openNewPage(url , title , displayNavigationBar , datasource , navIsTransparent);
}
function openNewPage( url , title , displayNavigationBar , datasource , navIsTransparent){
var barOptions = displayNavigationBar ? {
autoBackButton:true,
titleText:title, // 标题栏文字,当不设置此属性时,默认加载当前页面的标题,并自动更新页面的标题
titleColor:"#FF4500", // 字体颜色,颜色值格式为"#RRGGBB",默认值为"#000000"
titleSize:"17px", // 字体大小,默认17px
backgroundColor:"#fff", // 控件背景颜色,颜色值格式为"#RRGGBB",默认值为"#F7F7F7"
splitLine:{ // 标题栏控件的底部分割线,类似borderBottom
color:"#ddd", // 分割线颜色,默认值为"#CCCCCC"
height:"0.8px" // 分割线高度,默认值为"2px"
},
type: (url.indexOf('me-homepage') != -1) || navIsTransparent ? 'transparent' : 'default'
} : '';
mui.openWindow({
url:url,
id:url,
styles:{
bounce : "vertical",
titleNView: barOptions
},
extras:datasource,
createNew:true,
show:{
// autoShow:true,
event:'loaded',
// aniShow:"slide-in-right",
// duration:"2000"
},
waiting : {
autoShow:false
},
});
}
\ No newline at end of file
///弹框操作,选择日期、选择数据
function addEventForButton(picker){
///选中区域
var showLocationPickerBtn = document.getElementById('showLocationPickerBtn');
showLocationPickerBtn.addEventListener('tap', function(event) {
if(qyArr.length < 1){mui.alert('没有数据区域!');return;}
picker.setData(qyArr);
picker.show(function(items) {
var title = items[0]['text'];
var index = items[0]['index'];
showLocationPickerBtn.innerText = title;
selected_qy = qyOriginDataArr[index];
//清除下一关联级数据
showstationPickerBtn.innerText = '选择工位';
devicesPickerBtn.innerText = '选择设备';
sbOriginDataArr = [];
gwOriginDataArr = [];
selected_gw = null;
selected_sb = null;
console.log(window.location.pathname);
if(clearParameter){
clearParameter();
}
///加载工位数据
requestBaseData('gw' , {'nodeId':selected_qy['nodeId']});
});
}, false);
///选择工位
var showstationPickerBtn = document.getElementById('showStationPickerBtn');
showstationPickerBtn.addEventListener('tap', function(event) {
if(selected_qy == null){mui.alert('请先选择区域');return;}
if(gwOriginDataArr == null || gwOriginDataArr.length < 1){
///加载工位数据
requestBaseData('gw' , {'nodeId':selected_qy['nodeId']} , function(){
picker.setData(gwArr);
picker.show(function(items) {
var title = items[0]['text'];
var index = items[0]['index'];
showstationPickerBtn.innerText = title;
selected_gw = gwOriginDataArr[index];
devicesPickerBtn.innerText = '选择设备';
sbOriginDataArr = null;
selected_sb = null;
if(clearParameter){
clearParameter();
}
requestBaseData('sb' , {'nodeId':selected_gw['nodeId']});
});
});return;
}
picker.setData(gwArr);
picker.show(function(items) {
var title = items[0]['text'];
var index = items[0]['index'];
showstationPickerBtn.innerText = title;
selected_gw = gwOriginDataArr[index];
devicesPickerBtn.innerText = '选择设备';
sbOriginDataArr = null;
selected_sb = null;
if(clearParameter){
clearParameter();
}
requestBaseData('sb' , {'nodeId':selected_gw['nodeId']});
});
}, false);
///选择设备
var devicesPickerBtn = document.getElementById('showDevicesPicker');
devicesPickerBtn.addEventListener('tap', function(event) {
if(selected_gw == null){mui.alert('请先选择工位');return;}
if(sbOriginDataArr == null || sbOriginDataArr.length < 1){
requestBaseData('sb' , {'nodeId':selected_gw['nodeId']} , function(){
picker.setData(sbArr);
picker.show(function(items) {
var t = items[0]['text'];
var index = items[0]['index'];
devicesPickerBtn.innerText = t;
selected_sb = sbOriginDataArr[index];
if(clearParameter){
clearParameter();
}
});
});return;
}
picker.setData(sbArr);
picker.show(function(items) {
var t = items[0]['text'];
var index = items[0]['index'];
devicesPickerBtn.innerText = t;
selected_sb = sbOriginDataArr[index];
if(clearParameter){
clearParameter();
}
});
}, false);
}
///选择日期
function selectDateAction(pickDateBtn){
pickDateBtn.addEventListener('tap', function() {
var isStartDate = pickDateBtn.id == 'pickStartDateBtn';
var _self = this;
{
var id = this.getAttribute('id');
var optionsJson = this.getAttribute('data-options') || '{}';
var options = JSON.parse(optionsJson);
options['endDate'] = new Date();
var _title = this.innerText;
if(_title.length > 15){
options['value']= _title;
}
_self.picker = new mui.DtPicker(options);
_self.picker.show(function(rs) {
pickDateBtn.innerText = rs.text;
if(isStartDate){
_startDate = rs.text;
}else{
_endDate = rs.text;
}
_self.picker.dispose();
_self.picker = null;
});
}
}, false);
}
\ No newline at end of file
//处理图片的添加、显示、压缩、上传
var _url;
var _params;
var _publishSuccessCallback;
var _publishErrorCallback;
var maxImageNum = 9;//最大选择图片数
var selectedImagesArr = [];//已选择的图片
document.write("<script src='../../js/p/tt.image.picker.js'><\/script>");
//显示图片列表
function displayImageList(imagesArr){
var _width = (plus.screen.resolutionWidth - 30) / 3.0;
var root = document.getElementById('image-list');
root.innerHTML = '';
for (var i = 0; i < imagesArr.length; i++) {
var url = imagesArr[i];
var div = document.createElement('div');
div.className = 'image-wrap';
div.style.width = _width + 'px';
div.style.height = (_width + 20) + 'px';
div.id = 'image-index-' + i;
var div_ig = document.createElement('div');
div_ig.style.height = _width + 'px';
var ig = document.createElement('img');
ig.className = 'single-image';
ig.style.width = _width + 'px';
ig.style.height = (_width) + 'px';
ig.setAttribute('src' , url);
div_ig.appendChild(ig);
div.appendChild(div_ig);
var del = document.createElement('div');
del.style.width = _width + 'px';
del.style.height = (20) + 'px';
del.style.backgroundColor = 'white';
del.id = i;
var ig2 = document.createElement('img');
ig2.src = '../../images/dislikeicon_details@2x.png';
ig2.style.width = '20px';
ig2.style.marginLeft = (_width - 20) / 2.0 + 'px';
ig2.style.height = '20px';
ig2.style.padding = '3px';
del.appendChild(ig2);
//删除事件
del.addEventListener('tap',function(){
var btnid = this.id;
var delImage = document.getElementById('image-index-' + btnid);
// console.log(btnid);
var _ig = delImage.getElementsByClassName('single-image')[0];
for (let i = 0; i < selectedImagesArr.length; i++) {
var s = selectedImagesArr[i];
if(s == _ig.src){
selectedImagesArr.splice(i , 1);
break;
}
}
root.removeChild(delImage);
if(selectedImagesArr.length == maxImageNum - 1){
appendLastAddImage(root);
}
})
div.appendChild(del);
root.appendChild(div);
}
//添加按钮
if(selectedImagesArr.length < maxImageNum){
appendLastAddImage(root);
}
}
///添加操作按钮
function appendLastAddImage(list){
var _width = (plus.screen.resolutionWidth - 30) / 3.0;
var div = document.createElement('div');
div.className = 'image-wrap';
div.setAttribute('id' , 'add-button-id');
div.style.width = _width + 'px';
div.style.height = (_width) + 'px';
div.style.marginTop = '5px';
div.style.display = 'block';
var ig = document.createElement('img');
ig.className = 'single-image';
ig.setAttribute('src' , '../../images/addicon_repost@2x.png');
ig.style.padding = '35px';
div.appendChild(ig);
//添加事件
div.addEventListener('tap',function(){
ttShowActionSheetPickerImage(maxImageNum - selectedImagesArr.length , function(e){
//判断数据是数组还是字符,数组来自相册,字符串来自相册
var isFromAlbum = Array.isArray(e);
if(isFromAlbum){
selectedImagesArr.push.apply(selectedImagesArr ,e);
displayImageList(selectedImagesArr);
}else{
selectedImagesArr.push(e);
displayImageList(selectedImagesArr);
}
})
} , true)
list.appendChild(div);
}
/**
* 提交数据
*/
function submitToServer(url , params , successCallback , errorCallback){
_url = url;
_params = params;
_publishSuccessCallback = successCallback;
_publishErrorCallback = errorCallback;
var token , userJsonStr = localStorage.getItem("loginuserinfo");
if(userJsonStr){
var _u = JSON.parse(userJsonStr);
if(_u && _u['token']){
token = _u['token'];_params['t'] = token;
}
}
//压缩并上传提交
zipImageFile(selectedImagesArr);
}
/**
* 压缩图片、获取图片资源路径
*/
function zipImageFile(imagesArr){
var actions = [];
var files = [];
for (var i = 0; i < imagesArr.length; i++) {
var path = imagesArr[i];
var pro = new Promise(resolve => {
var name = path.substr(path.lastIndexOf('/') + 1);
// console.log("zip file name:"+name);
plus.zip.compressImage({
src: path,
dst: '_doc/' + name,
overwrite: true,
quality: 50
},function(event){
// console.log(JSON.stringify(event));
files.push(event.target);
resolve();
},function(error){
console.log(error.code);
})
});
actions.push(pro);
}
Promise.all(actions).then(function(){
// console.log('压缩图片完成:' + files.length + ' 个');
var hud = plus.nativeUI.showWaiting('数据提交中');
uploadFileData(BASE_URL + (_url || publish_url) , _params , files , function(){
hud.close();
if(_publishSuccessCallback){
_publishSuccessCallback()
}else{
mui.alert('系统24小时内审核通过后才会显示,感谢关注!','发布成功','知道了',function (e) {
mui.back();
});
}
} , function(errorMsg){
hud.close();
plus.nativeUI.toast(errorMsg , {verticalAlign: 'center'});
});
});
}
/**提交数据到服务器
* url:提交地址
* params:请求参数
* filesArr:要上传的图片
* success:成功回调
* failure:失败回调
*/
function uploadFileData(url , params , filesArr , success,failure){
if(window.plus && plus.networkinfo.getCurrentType() === plus.networkinfo.CONNECTION_NONE) {
plus.nativeUI.toast('无法连接网络!', {
verticalAlign: 'top'
});return;
}
if(filesArr.length > 0){
var task = plus.uploader.createUpload(url, {method:"POST"},
function ( t, status ) {
// console.log(JSON.stringify(t));
if ( status == 200 ) {
if(success){
success();
}
} else {
if(failure){
failure()
}
}
}
);
for (var key in params) {task.addData(key , params[key]);}
for (var i = 0; i < filesArr.length; i++) {
var ig = filesArr[i];
var k = 'files[' + i + ']';
task.addFile( ig, {key:k , mime:'image/jpeg'} );
}
task.start();
}else{
api_post(_url || publish_url , params , function(res){
if(success){
success();
}
} , function(error){
if(failure){
failure(error);
}
})
}
}
\ No newline at end of file
//从相机或相册选择图片操作
//plus中调用
var didFinishedSelectedImageHandler;//选择图片完成后的回调方法
//弹框提示选择图片(相机和相册)
/**
* @param {Object} maxImageNum 选择图片数(从相册时用)
* @param {Object} successCallBack
*/
function ttShowActionSheetPickerImage(maxImageNum , successCallBack){
didFinishedSelectedImageHandler = successCallBack;
plus.nativeUI.actionSheet({title:'添加图片' , cancel:'取消' , buttons:[{title:'拍照'},{title:'从相册选取'}] }, function(e){
switch (e.index){
case 1:selectFromPhotos();break;
case 2:selectFromAlbum(maxImageNum);break;
default:break;
}
})
}
//拍照获取图片
function selectFromPhotos() {
var c = plus.camera.getCamera();
c.captureImage(function(e) {
//console.log(e);
var name = e.substr(e.lastIndexOf('/') + 1);
plus.zip.compressImage({
src: e,
dst: '_doc/' + name,
overwrite: true,
quality: 100
},function(event){
if(didFinishedSelectedImageHandler){
didFinishedSelectedImageHandler(event.target);
}
},function(error){
console.log(error.code);
})
}, function(s) {
console.log("拍照失败:" + s);
}, {
filename: "_doc/camera/"
})
}
//从相册中选择图片
function selectFromAlbum(imageNum){
plus.gallery.pick( function(e){
if(didFinishedSelectedImageHandler){
didFinishedSelectedImageHandler(e.files);
}
}, function (e) {
plus.nativeUI.toast('取消选择图片');
},{
filter: "image",
multiple:true,
maximum: imageNum,
system: false,
onmaxed: function() {
plus.nativeUI.alert('最多只能选择' + imageNum + '张图片');
}
}
);
}
module.exports = {
ttShowActionSheetPickerImage:ttShowActionSheetPickerImage
}
\ No newline at end of file
//刷新处理操作
var pageNum = 1;//当前页
var pageItemsLen = 20;//每页条数
var isPullDownRefreshing = true;//正在下拉刷新
var dataSourceArr = [];//当前列表数据源
///调用者设置
var _id;
var _url;
var _requestParamters;
var _successCallBack;
var _failureCallBack;
/**刷新列表初始化(必须)
* containerId:列表容器ID(必须)
* url:请求地址(必须)
* pars:请求参数(可选)
* success:成功回调(必须)
* error:失败回调(可选)
*/
function ttRefreshInit(containerId , url , pars , success , error ){
this._id = containerId;
this._url = url;
this._requestParamters = pars;
this._successCallBack = success;
this._failureCallBack = error;
}
//下拉刷新
function pulldownRefresh() {
pageNum = 1;
dataSourceArr = [];
isPullDownRefreshing = true;
refreshRequestData();
}
//上拉加载更多
function loadMoreData(){
pageNum = pageNum + 1;
isPullDownRefreshing = false;
refreshRequestData();
}
function refreshRequestData(){
if(_url == null){plus.nativeUI.toast('请求地址不能为空!',{verticalAlign:'center'});return;}
_requestParamters['pageNumber'] = pageNum;
// plus.nativeUI.showWaiting('数据加载中');
// console.log('---本次请求参数:' + JSON.stringify(_requestParamters));
api_post(_url , _requestParamters ,function(result){
console.log('当前页:' + pageNum + '\t本次返回数据长度:' + (result ? result.length : 0));
// plus.nativeUI.closeWaiting();
var arr = result;
if(isPullDownRefreshing){
// console.log(_id);
mui(_id).pullRefresh().endPulldownToRefresh();
mui(_id).pullRefresh().refresh(true);
if(!arr || result.length < pageItemsLen){
mui(_id).pullRefresh().disablePullupToRefresh();
mui(_id).pullRefresh().endPullupToRefresh(true);
}
}else{
if(arr){
if(result.length < pageItemsLen){
mui(_id).pullRefresh().disablePullupToRefresh();
}
mui(_id).pullRefresh().endPullupToRefresh(result.length < pageItemsLen);
}else{
mui(_id).pullRefresh().disablePullupToRefresh();
mui(_id).pullRefresh().endPullupToRefresh(true);
plus.nativeUI.toast('加载完成');
var isexistnodatadiv = document.getElementById('refreshtablenodataid');
if(!isexistnodatadiv){
var nodatadiv = document.createElement('div');
nodatadiv.id = 'refreshtablenodataid';
nodatadiv.innerText = '已经是底线了^_^';
nodatadiv.setAttribute('style','text-align:center;margin-top:30px;color:#999;font-size:13px;');
var _root = document.getElementById(_id.substr(1));
_root.appendChild(nodatadiv);
mui(_id).pullRefresh().disablePullupToRefresh();
mui(_id).pullRefresh().endPullupToRefresh(true);
}
return;
}
}
if(arr && _successCallBack){_successCallBack(arr);}
if(pageNum == 1){
if(!arr){
var nodatadiv = document.createElement('div');
nodatadiv.innerText = '暂时还没有数据';
nodatadiv.setAttribute('style','text-align:center;margin-top:50%;color:#999;font-size:13px;');
nodatadiv.id = 'notanydataid';
var _root = document.getElementById(_id.substr(1));
_root.innerHTML = '';
_root.appendChild(nodatadiv);
mui(_id).pullRefresh().disablePullupToRefresh();
// mui(_id).pullRefresh().disablePulldownToRefresh();
_successCallBack(arr || '');
}else{
if(arr.length < pageItemsLen){
var notanydata = document.getElementById('notanydataid');
if(notanydata){
var _root = document.getElementById(_id.substr(1));
_root.removeChild(notanydata);
// notanydata.parentNode.removeChild(notanydata);
}
var isexistnodatadiv = document.getElementById('refreshtablenodataid');
if(!isexistnodatadiv){
var nodatadiv = document.createElement('div');
nodatadiv.id = 'refreshtablenodataid';
nodatadiv.innerText = '已经是底线了^_^';
nodatadiv.setAttribute('style','text-align:center;margin-top:30px;color:#999;font-size:13px;');
var _root = document.getElementById(_id.substr(1));
_root.appendChild(nodatadiv);
mui(_id).pullRefresh().disablePullupToRefresh();
mui(_id).pullRefresh().endPullupToRefresh(true);
}
}else{//使能上拉
mui(_id).pullRefresh().refresh(true);
}
}
return;
}
// if(arr && _successCallBack){_successCallBack(arr);}
plus.nativeUI.toast('加载完成');
} ,function(error){
pageNum = pageNum - 1;
plus.nativeUI.closeWaiting();
if(isPullDownRefreshing){
mui(_id).pullRefresh().endPulldownToRefresh();
mui(_id).pullRefresh().refresh(true);
}else{
mui(_id).pullRefresh().endPullupToRefresh(false);
}
if(_failureCallBack){
_failureCallBack();
}
plus.nativeUI.toast(error);
})
}
//刷新处理操作
var pageNum = 1;//当前页
var pageItemsLen = 20;//每页条数
var isPullDownRefreshing = true;//正在下拉刷新
var dataSourceArr = [];//当前列表数据源
///调用者设置
var _id;
var _url;
var _requestParamters;
var _successCallBack;
var _failureCallBack;
/**刷新列表初始化(必须)
* containerId:列表容器ID(必须)
* url:请求地址(必须)
* pars:请求参数(可选)
* success:成功回调(必须)
* error:失败回调(可选)
*/
function ttRefreshInit(containerId , url , pars , success , error ){
this._id = containerId;
this._url = url;
this._requestParamters = pars;
this._successCallBack = success;
this._failureCallBack = error;
}
//下拉刷新
function pulldownRefresh() {
pageNum = 1;
dataSourceArr = [];
isPullDownRefreshing = true;
refreshRequestData();
}
//上拉加载更多
function loadMoreData(){
pageNum = pageNum + 1;
isPullDownRefreshing = false;
refreshRequestData();
}
function refreshRequestData(){
if(_url == null){plus.nativeUI.toast('请求地址不能为空!',{verticalAlign:'center'});return;}
_requestParamters['pageNumber'] = pageNum;
api_post(_url , _requestParamters ,function(result){
console.log('当前页:' + pageNum + '\t本次返回数据长度:' + (result ? result.length : 0));
var arr = result;
if(isPullDownRefreshing){
mui(_id).pullRefresh().endPulldownToRefresh();
mui(_id).pullRefresh().refresh(true);
}else{
if(arr){
mui(_id).pullRefresh().endPullupToRefresh(result.length < pageItemsLen);
}else{
mui(_id).pullRefresh().endPullupToRefresh(true);
plus.nativeUI.toast('加载完成');return;
}
}
if(arr && _successCallBack){_successCallBack(arr);}
plus.nativeUI.toast('加载完成');
} ,function(error){
if(isPullDownRefreshing){
mui(_id).pullRefresh().endPulldownToRefresh();
mui(_id).pullRefresh().refresh(true);
}else{
mui(_id).pullRefresh().endPullupToRefresh(false);
}
if(_failureCallBack){
_failureCallBack();
}
plus.nativeUI.toast(error);
})
}
var USER_OP = {
/**
* 删除动态
* item:动态对象
*/
deletePost: function(item){
mui.confirm("确定删除这条动态?", ["确定", "取消"], function(e) {
if(e.index == 0){
var _category = getItemCategory(item['type']);
var d = {"uid":getLoginUid() ,
"pid": item['pid'],
"category":_category,
"type":0};
hud_show('正在删除');
api_post(delete_sc_url , d , function(res){
hud_close('删除成功');
//删除列表元素
var l = document.getElementById(item['pid']);
l.parentNode.removeChild(l);
} , function(error){
hud_close(error);
})
}
});
},
//
}
\ No newline at end of file
/**
* 当前登录用户信息
*/
//用户ID
function getLoginUid(){
var u = getUserInfo();
if(!u){return ;}
return u['user_id'];
}
//是否登录
function userHasLogined(){
var b = getLoginUid() != null;
if(!b){
console.log('还没有登录....');
}
return b;
}
function getUserInfo(){
var s = uni.getStorageSync('loginuserinfo');
return s;
}
//获取动态列表缩略图
function getDtImageUrl(thumbUrl , defaultUrl){
if(thumbUrl){
thumbUrl = thumbUrl.replace('.jpg' , '_thumb.jpg');
}
return thumbUrl || defaultUrl;
}
function userAvatar(user , defaultAvatar){
var u_avatar = user['avatar_thumb'];
if(u_avatar == null || u_avatar == ''){
u_avatar = defaultAvatar;
}
return u_avatar;
}
module.exports = {
userInfo:getUserInfo,
uid:getLoginUid,
isLogined:userHasLogined
}
\ No newline at end of file
This diff is collapsed. Click to expand it.
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));
\ No newline at end of file
function formatTime(time) {
if (typeof time !== 'number' || time < 0) {
return time
}
var hour = parseInt(time / 3600)
time = time % 3600
var minute = parseInt(time / 60)
time = time % 60
var second = time
return ([hour, minute, second]).map(function (n) {
n = n.toString()
return n[1] ? n : '0' + n
}).join(':')
}
function formatLocation(longitude, latitude) {
if (typeof longitude === 'string' && typeof latitude === 'string') {
longitude = parseFloat(longitude)
latitude = parseFloat(latitude)
}
longitude = longitude.toFixed(2)
latitude = latitude.toFixed(2)
return {
longitude: longitude.toString().split('.'),
latitude: latitude.toString().split('.')
}
}
var dateUtils = {
UNITS: {
'年': 31557600000,
'月': 2629800000,
'天': 86400000,
'小时': 3600000,
'分钟': 60000,
'秒': 1000
},
humanize: function (milliseconds) {
var humanize = '';
for (var key in this.UNITS) {
if (milliseconds >= this.UNITS[key]) {
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
break;
}
}
return humanize || '刚刚';
},
format: function (dateStr) {
var date = this.parse(dateStr)
var diff = Date.now() - date.getTime();
if (diff < this.UNITS['天']) {
return this.humanize(diff);
}
var _format = function (number) {
return (number < 10 ? ('0' + number) : number);
};
return date.getFullYear() + '-' + _format(date.getMonth() + 1) + '-' + _format(date.getDate());
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDay()) + '-' +
_format(date.getHours()) + ':' + _format(date.getMinutes());
},
parse: function (str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
var a = str.split(/[^0-9]/);
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
}
};
module.exports = {
formatTime: formatTime,
formatLocation: formatLocation,
dateUtils: dateUtils
}
## 使用注意
- 引入该组件,用v-if控制组件,组件create会触发喷发特效函数,然后可以传入一些位置参数,具体参考组件内的props属性,每个属性都备注了
-
## 示例代码
```
<template>
<view>
<fireworks v-if="isReady" />
</view>
</template>
<script>
import fireworks from '@/components/fireworks/index.vue'
export default {
data() {
return {
isReady: false
}
},
components: {
fireworks
},
onReady() {
this.$nextTick(() => {//后面记得销毁哈,不使用时设置为false
setTimeout(() => {
this.isReady = true;
}, 50)
})
},
}
</script>
```
\ No newline at end of file
<template>
<canvas class="fire-canvas" :style="{width: width + 'px', height: height + 'px', 'z-index': zIndex}"
:canvas-id="canvasId" @error="canvasIdErrorCallback"></canvas>
</template>
<script>
/*
浏览器的最高刷新赔率(最后一个表示1秒刷新60次)
*/
const minBrowserRefreshTime = window && (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame) || function(t) {
setTimeout(t, 1e3 / 60)
}
const systenInfo = uni.getSystemInfoSync();
let fireCanvasBox = null;
export default {
props: {
/*
礼花数量(最好小于500,太多会卡顿)
*/
particleCount: {
type: [Number, String],
default: 80
},
/*取值 0-360
喷发角度示意图(简单说就是喷射方向)
礼花(90)
礼花(180) 礼花0
礼花(270)
*/
angle: {
type: [Number, String],
default: 90
},
/*
爆炸范围
*/
spread: {
type: [Number, String],
default: 100
},
/*
喷发的初始速度
*/
startVelocity: {
type: [Number, String],
default: 45
},
/*
喷发的衰退时间,超出canvas会被清除,跟startVelocity配合使用
*/
decay: {
type: [Number, String],
default: 0.9
},
/*
刷新几次消失(其实是透明度为0),这个跟间隔的刷新频率有关
*/
ticks: {
type: [Number, String],
default: 150
},
/*
礼花层级
*/
zIndex: {
type: [Number, String],
default: 1
},
/*
所有要随机的礼花颜色预选值
*/
colors: {
type: Array,
default: () => ["#5BC0EB", "#2176AE", "#FDE74C", "#9BC53D", "#E55934", "#FA7921", "#FF4242"]
},
canvasId: {
type: String,
default: 'fireCanvas'
},
/*
canvas宽度(单位px)
*/
width: {
type: [Number, String],
default: () => {
return systenInfo.windowWidth
}
},
/*
canvas高度(单位px)
*/
height: {
type: [Number, String],
default: () => {
return systenInfo.windowHeight
}
},
/*
中心点-x
*/
x: {
type: [Number, String],
default: () => {
return systenInfo.windowWidth / 2
}
},
/*
中心点-y
*/
y: {
type: [Number, String],
default: () => {
return systenInfo.windowHeight * 0.4
}
}
},
data() {
return {
/*
手机分辨率
*/
pixelRatio: systenInfo.pixelRatio
}
},
onShow(){
console.log('onShow');
this.initCanvas();
}, created() {
console.log('created');
this.initCanvas();
},
methods: {
open(){
},
/*
转16进制(颜色用)
*/
parseInt16(t) {
return parseInt(t, 16);
},
canvasIdErrorCallback(e) {
console.error(e.detail.errMsg)
},
initCanvas() {
fireCanvasBox = null;
fireCanvasBox = uni.createCanvasContext(this.canvasId, this);
fireCanvasBox.fillRect(0, 0, this.width * this.pixelRatio, this.height * this.pixelRatio);
fireCanvasBox.scale(this.pixelRatio,this.pixelRatio);
fireCanvasBox.save();
this.fireworksDraw();
},
fireworksDraw() {
let ribbon = [] ,//彩带容器
particleCount = this.particleCount, n = null, r = null, a = null,i = null;
for (; particleCount--;){
n = {
x: this.x,
y: this.y,
angle: this.angle,
spread: this.spread,
startVelocity: this.startVelocity,
color: this.colors[particleCount % this.colors.length],
ticks: this.ticks,
decay: this.decay
},
i = 0,
r = n.angle * (Math.PI / 180),
a = n.spread * (Math.PI / 180);
ribbon.push({//菜单位置初始化
x: n.x,
y: n.y,
depth: .5 * Math.random() + .6,
wobble: 10 * Math.random(),
velocity: .5 * n.startVelocity + Math.random() * n.startVelocity,
angle2D: -r + (.5 * a - Math.random() * a),
tiltAngle: Math.random() * Math.PI,
color: (i = (n.color + "").replace(/[^0-9a-f]/gi, ""), i.length < 6 && (i = i[0] + i[0] + i[1] + i[1] + i[2] + i[2]), {//生成随机颜色
r: this.parseInt16(i.substring(0, 2)),
g: this.parseInt16(i.substring(2, 4)),
b: this.parseInt16(i.substring(4, 6))
}),
tick: 0,
totalTicks: n.ticks,
decay: n.decay,
random: Math.random() + 5,
tiltSin: 0,
tiltCos: 0,
wobbleX: 0,
wobbleY: 0
})
}
minBrowserRefreshTime(function drawRibbon() {
if(!fireCanvasBox) return ;
fireCanvasBox.draw(),
fireCanvasBox.restore(),
ribbon = ribbon.filter((e) => {
e.x += Math.cos(e.angle2D) * e.velocity,
e.y += Math.sin(e.angle2D) * e.velocity + 5 * e.depth,
e.wobble += .1,
e.velocity *= e.decay,
e.tiltAngle += .02 * Math.random() + .12,
e.tiltSin = Math.sin(e.tiltAngle),
e.tiltCos = Math.cos(e.tiltAngle),
e.random = Math.random() + 4,
e.wobbleX = e.x + 10 * Math.cos(e.wobble) * e.depth,
e.wobbleY = e.y + 10 * Math.sin(e.wobble) * e.depth;
// 开始画图
fireCanvasBox.fillStyle="rgba(" + e.color.r + ", " + e.color.g + ", " + e.color.b + ", " + (1 - (e.tick++) / e.totalTicks) + ")",
fireCanvasBox.beginPath(),
fireCanvasBox.moveTo(Math.floor(e.x),Math.floor(e.y)),
fireCanvasBox.lineTo(Math.floor(e.wobbleX),Math.floor(e.y + e.random * e.tiltSin)),
fireCanvasBox.lineTo(Math.floor(e.wobbleX + e.random * e.tiltCos),Math.floor(e.wobbleY + e.random * e.tiltSin)),
fireCanvasBox.lineTo(Math.floor(e.x + e.random * e.tiltCos),Math.floor(e.wobbleY)),
fireCanvasBox.closePath(),
fireCanvasBox.fill();
return e.tick < e.totalTicks
})
ribbon.length ? minBrowserRefreshTime(drawRibbon): fireCanvasBox = null;//轮询调用或者释放掉
}
)
}
},
}
</script>
<style>
.fire-canvas{
position: fixed;
top: 0px;
left: 0px;
pointer-events: none;
z-index: 99999999;
}
</style>
<template>
<view class="fr_img">
<!-- 主图 -->
<image class="fr_img_content"
:src="src" :mode="mode" :lazy-load="lazyLoad" :webp="webp" :show-menu-by-longpress="showMenuByLongpress" @error="onImgError" @load="onImgLoad"/>
<view v-if="loading_complete && completeTransition" class="loading_complete_transition"></view>
<!-- 加载失败图 -->
<view v-if="loading_error" class="loading_error"> <image class="loading_error_img" :src="loadingErrorImg" mode="aspectFit"></image> </view>
<!-- 加载中图 -->
<view v-else-if="!loading_complete" class="loading">
<image v-if="loadingIngImg == 'two-balls'" class="loading_img" :src="require('./loading_two_balls.gif')" mode="aspectFit"></image>
<view v-if="loadingIngImg == 'oblique-light'" class="loading_oblique_light"></view>
<view v-if="loadingIngImg == 'looming'" class="loading_looming"></view>
</view>
</view>
</template>
<script>
export default {
props: {
// 和官方Image组件属性一致
src: {
type: String,
default: "",
},
mode: {
type: String,
default: "",
},
lazyLoad: {
type: Boolean,
default: false,
},
webp: {
type: Boolean,
default: false,
},
showMenuByLongpress: {
type: Boolean,
default: false,
},
// 可选: 加载失败图片:可以本地url、网络url、base64 (与src一致)
loadingErrorImg: {
type: String,
default: require('./loading_error.png'),
},
// 可选: 加载中的图片
// two-balls = 两个球来回转
// oblique-light = 斜光
// looming = 若影若现
// 本地url、网络url、base64 = 自定义的加载中图片(与src一致)
loadingIngImg: {
type: String,
default: "oblique-light",
},
// 可选:是否需要加载完成动画
completeTransition: {
type: Boolean,
default: true,
},
},
data() {
return {
loading_complete: false,
loading_error: false,
};
},
methods: {
onImgError: function(event){
this.loading_error = true;
this.$emit("error", event);
},
onImgLoad: function(event){
this.loading_complete = true;
this.$emit("load", event);
},
},
}
</script>
<style lang="scss">
.fr_img{
width: 100%;
height: 100%;
position: relative;
.fr_img_content{
width: 100%;
height: 100%;
position: absolute;
}
.loading_complete_transition{
width: 100%;
height: 100%;
position: absolute;
background-color: #FFFFFF;
animation: loading_complete_transition 1.2s forwards;
}
@keyframes loading_complete_transition{
0% { opacity: 1; }
100% { opacity: 0; }
}
.loading_error{
width: 100%;
height: 100%;
background-color: #F8F8F8;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
.loading_error_img{
width: 100rpx;
height: 100rpx;
max-width: 100%;
max-height: 100%;
}
}
.loading{
width: 100%;
height: 100%;
background-color: #FFFFFF;
position: absolute;
display: flex;
justify-content: center;
align-items: center;
// 加载图
.loading_img{
width: 100rpx;
height: 100rpx;
max-width: 100%;
max-height: 100%;
}
// 斜光
.loading_oblique_light{
width: 100%;
height: 100%;
background-color: #e3e3e3;
background-image: linear-gradient(100deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 80%);
background-size: 100rpx 100%;
background-repeat: repeat-y;
background-position:0 0;
animation: loading_oblique_light .6s infinite;
}
@keyframes loading_oblique_light {
to {
background-position: 200% 0;
}
}
// 若隐若现
.loading_looming{
width: 100%;
height: 100%;
animation: loading_looming 1s infinite linear;
background-color: #e3e3e3;
}
@keyframes loading_looming{
0% {background-color:rgba($color: #e3e3e3, $alpha: 0.5);}
50% {background-color:rgba($color: #e3e3e3, $alpha: 1.0);}
100% {background-color:rgba($color: #e3e3e3, $alpha: 0.5);}
}
}
}
</style>
<template>
<view>
<picker mode="multiSelector" :range="dateSelectorRange" :value="selectedDateValue" @columnchange="onDateColumnChange"
@change="onDateChange">
<view>{{currSelectedDate}}</view>
</picker>
</view>
</template>
<script>
const currDate = new Date();
const currYear = currDate.getFullYear();
const currMonth = currDate.getMonth() + 1;
const currDay = currDate.getDate();
var _selectedY,_selectedM,_selectedD;
export default {
props: {
config: {
type: Object,
default: function() {
return {
initType: "ymd",
yearsBefore: 5,
yearsAfter: 5,
initDate:""
}
}
}
},
data() {
return {
yyyyArr: [],
mmArr: [],
ddArr: [],
currSelectedDate:"",
selectedDateValue:null
};
},
computed: {
dateSelectorRange: function() {
const _this = this;
if ("ym" == _this.config.initType) {
return [_this.yyyyArr, _this.mmArr];
} else {
return [_this.yyyyArr, _this.mmArr, _this.ddArr];
}
}
},
created() {
const _this = this;
// console.log("======created=====",_this.config);
_this.getYearArr();
_this.getMMArr();
let mmStr = (currMonth < 10 ? "0" + currMonth : currMonth);
if ("ym" != _this.config.initType) {
if(_this.config.initDate){
_this.currSelectedDate = _this.config.initDate;
}else{
_this.currSelectedDate = currYear + "-" + mmStr + "-" + (currDay < 10 ? "0" + currDay :currDay); //创建时默认选中当前日期
}
_this.getDDArr(currYear,mmStr);
} else {
if(_this.config.initDate){
_this.currSelectedDate = _this.config.initDate;
}else{
_this.currSelectedDate = currYear + "-" + mmStr;
}
}
_this.initSelectedDateValue();
},
methods: {
getYearArr() {
//根据配置获取年份数组
const _this = this;
if (_this.config.yearsAfter && _this.config.yearsAfter > 0) {
for (let i = 0; i < _this.config.yearsAfter; i++) {
_this.yyyyArr.push(currYear + _this.config.yearsAfter - i);
}
}
_this.yyyyArr.push(currYear);
if (_this.config.yearsBefore && _this.config.yearsBefore > 0) {
for (let i = 1; i <= _this.config.yearsBefore; i++) {
_this.yyyyArr.push(currYear - i);
}
}
_this.yyyyArr = _this.yyyyArr.reverse()
},
getMMArr() {
//初始化月份数组
const _this = this;
for (let i = 1; i <= 12; i++) {
_this.mmArr.push(i < 10 ? "0" + i : ""+i);
}
},
getDDArr(y,m) {
//根据当前选中的年月动态计算天数数组
const _this = this;
let mmDays = 31;
if(["04","06","09","11"].indexOf(m)>=0){
mmDays = 30;
}else if("02"==m){
if(y%400==0 || (y%4==0 && y%100!=0) ){
mmDays = 29;
}else{
mmDays = 28;
}
}else{
mmDays = 31;
}
_this.ddArr = [];
for (let i = 1; i <= mmDays; i++) {
_this.ddArr.push(i < 10 ? "0" + i : ""+i);
}
},
initSelectedDateValue(){
const _this = this;
if(_this.currSelectedDate && _this.currSelectedDate.indexOf("-")>0){
let dateArr = _this.currSelectedDate.split("-");
if(2 == dateArr.length || 3 == dateArr.length){
let yyyyIdx = 0;
let mmIdx = 0;
for (let i = 0; i < _this.yyyyArr.length; i++) {
if(_this.yyyyArr[i] == dateArr[0]){
yyyyIdx = i;
break;
}
}
for (let j = 0; j < _this.mmArr.length; j++) {
if(_this.mmArr[j] == dateArr[1]){
mmIdx = j;
break;
}
}
if(3 == dateArr.length && "ym" != _this.config.initType){
let ddIdx = 0;
for (let k = 0; k < _this.ddArr.length; k++) {
if(_this.ddArr[k] == dateArr[2]){
ddIdx = k;
break;
}
}
_this.selectedDateValue = [yyyyIdx,mmIdx,ddIdx];
}else{
_this.selectedDateValue = [yyyyIdx,mmIdx];
}
}else{
uni.showToast({
icon:"none",
title:"初始化日期格式错误"
});
}
}
},
onDateColumnChange(e) {
const _this = this;
// this.$emit("onDateColumnChange", e);
if(_this.selectedDateValue && _this.selectedDateValue.length>0){
_this.selectedDateValue[e.detail.column] = e.detail.value;
}
if("ym" != _this.config.initType){
if(0 == e.detail.column){
let _yy = _this.yyyyArr[e.detail.value];
let _mm = _this.mmArr[_this.selectedDateValue[1]];
_this.getDDArr(_yy,_mm);
}else if(1 == e.detail.column){
let _yy = _this.yyyyArr[_this.selectedDateValue[0]];
let _mm = _this.mmArr[e.detail.value];
_this.getDDArr(_yy,_mm);
}else{
//日变化无需处理
}
if(_this.selectedDateValue[2]>=_this.ddArr.length){
_this.selectedDateValue[2] = _this.ddArr.length - 1;
}
}
},
onDateChange(e) {
let yyyy = this.dateSelectorRange[0][e.detail.value[0]];
let mm = this.dateSelectorRange[1][e.detail.value[1]];
if("ym"!=this.config.initType){
let dd = this.dateSelectorRange[2][e.detail.value[2]];
this.currSelectedDate = `${yyyy}-${mm}-${dd}`;
}else{
this.currSelectedDate = `${yyyy}-${mm}`;
}
this.$emit("onDateChange", {
value: this.currSelectedDate
});
},
initDate(d){
console.log("=======initDate========",d);
const _this = this;
_this.currSelectedDate = d;
_this.initSelectedDateValue();
}
}
}
</script>
<style>
</style>
This source diff could not be displayed because it is too large. You can view the blob instead.
/* eslint-disable */
var provinceData = [{
"label": "北京市",
"value": "11"
},
{
"label": "天津市",
"value": "12"
},
{
"label": "河北省",
"value": "13"
},
{
"label": "山西省",
"value": "14"
},
{
"label": "内蒙古自治区",
"value": "15"
},
{
"label": "辽宁省",
"value": "21"
},
{
"label": "吉林省",
"value": "22"
},
{
"label": "黑龙江省",
"value": "23"
},
{
"label": "上海市",
"value": "31"
},
{
"label": "江苏省",
"value": "32"
},
{
"label": "浙江省",
"value": "33"
},
{
"label": "安徽省",
"value": "34"
},
{
"label": "福建省",
"value": "35"
},
{
"label": "江西省",
"value": "36"
},
{
"label": "山东省",
"value": "37"
},
{
"label": "河南省",
"value": "41"
},
{
"label": "湖北省",
"value": "42"
},
{
"label": "湖南省",
"value": "43"
},
{
"label": "广东省",
"value": "44"
},
{
"label": "广西壮族自治区",
"value": "45"
},
{
"label": "海南省",
"value": "46"
},
{
"label": "重庆市",
"value": "50"
},
{
"label": "四川省",
"value": "51"
},
{
"label": "贵州省",
"value": "52"
},
{
"label": "云南省",
"value": "53"
},
{
"label": "西藏自治区",
"value": "54"
},
{
"label": "陕西省",
"value": "61"
},
{
"label": "甘肃省",
"value": "62"
},
{
"label": "青海省",
"value": "63"
},
{
"label": "宁夏回族自治区",
"value": "64"
},
{
"label": "新疆维吾尔自治区",
"value": "65"
},
{
"label": "台湾",
"value": "66"
},
{
"label": "香港",
"value": "67"
},
{
"label": "澳门",
"value": "68"
}
]
export default provinceData;
<template>
<div class="mpvue-picker">
<div :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></div>
<div class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
<div class="mpvue-picker__hd" catchtouchmove="true">
<div class="mpvue-picker__action" @click="pickerCancel">取消</div>
<div class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</div>
</div>
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange">
<block>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in provinceDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in cityDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in areaDataList" :key="index">{{item.label}}</div>
</picker-view-column>
</block>
</picker-view>
</div>
</div>
</template>
<script>
import provinceData from './city-data/province.js';
import cityData from './city-data/city.js';
import areaData from './city-data/area.js';
export default {
data() {
return {
pickerValue: [0, 0, 0],
provinceDataList: provinceData,
cityDataList: cityData[0],
areaDataList: areaData[0][0],
/* 是否显示控件 */
showPicker: false,
};
},
created() {
this.init()
},
props: {
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return [0, 0, 0]
}
},
/* 主题色 */
themeColor: String
},
watch: {
pickerValueDefault() {
this.init();
}
},
methods: {
init() {
this.handPickValueDefault(); // 对 pickerValueDefault 做兼容处理
const pickerValueDefault = this.pickerValueDefault
this.cityDataList = cityData[pickerValueDefault[0]];
this.areaDataList = areaData[pickerValueDefault[0]][pickerValueDefault[1]];
this.pickerValue = pickerValueDefault;
},
show() {
setTimeout(() => {
this.showPicker = true;
}, 0);
},
maskClick() {
this.pickerCancel();
},
pickerCancel() {
this.showPicker = false;
this._$emit('onCancel');
},
pickerConfirm(e) {
this.showPicker = false;
this._$emit('onConfirm');
},
showPickerView() {
this.showPicker = true;
},
handPickValueDefault() {
const pickerValueDefault = this.pickerValueDefault
let provinceIndex = pickerValueDefault[0]
let cityIndex = pickerValueDefault[1]
const areaIndex = pickerValueDefault[2]
if (
provinceIndex !== 0 ||
cityIndex !== 0 ||
areaIndex !== 0
) {
if (provinceIndex > provinceData.length - 1) {
this.pickerValueDefault[0] = provinceIndex = provinceData.length - 1;
}
if (cityIndex > cityData[provinceIndex].length - 1) {
this.pickerValueDefault[1] = cityIndex = cityData[provinceIndex].length - 1;
}
if (areaIndex > areaData[provinceIndex][cityIndex].length - 1) {
this.pickerValueDefault[2] = areaData[provinceIndex][cityIndex].length - 1;
}
}
},
pickerChange(e) {
let changePickerValue = e.mp.detail.value;
if (this.pickerValue[0] !== changePickerValue[0]) {
// 第一级发生滚动
this.cityDataList = cityData[changePickerValue[0]];
this.areaDataList = areaData[changePickerValue[0]][0];
changePickerValue[1] = 0;
changePickerValue[2] = 0;
} else if (this.pickerValue[1] !== changePickerValue[1]) {
// 第二级滚动
this.areaDataList =
areaData[changePickerValue[0]][changePickerValue[1]];
changePickerValue[2] = 0;
}
this.pickerValue = changePickerValue;
this._$emit('onChange');
},
_$emit(emitName) {
let pickObj = {
label: this._getLabel(),
value: this.pickerValue,
cityCode: this._getCityCode()
};
this.$emit(emitName, pickObj);
},
_getLabel() {
let pcikerLabel =
this.provinceDataList[this.pickerValue[0]].label +
//'-' +
this.cityDataList[this.pickerValue[1]].label +
//'-' +
this.areaDataList[this.pickerValue[2]].label;
return pcikerLabel;
},
_getCityCode() {
return this.areaDataList[this.pickerValue[2]].value;
}
}
};
</script>
<style>
.pickerMask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.mpvue-picker-content {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
}
.mpvue-picker-view-show {
transform: translateY(0);
}
.mpvue-picker__hd {
display: flex;
padding: 9px 15px;
background-color: #fff;
position: relative;
text-align: center;
font-size: 17px;
}
.mpvue-picker__hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.mpvue-picker__action {
display: block;
flex: 1;
color: #1aad19;
}
.mpvue-picker__action:first-child {
text-align: left;
color: #888;
}
.mpvue-picker__action:last-child {
text-align: right;
}
.picker-item {
text-align: center;
line-height: 40px;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 16px;
}
.mpvue-picker-view {
position: relative;
bottom: 0;
left: 0;
width: 100%;
height: 238px;
background-color: rgba(255, 255, 255, 1);
}
</style>
<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>
<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"
style="display:block;vertical-align:top;vertical-align:bottom;font-size:0;"/>
</template>
<script>
export default {
name: 'wxParseImg',
data() {
return {
newStyleStr: '',
preview: true,
};
},
props: {
node: {
type: Object,
default () {
return {};
},
},
},
inject: ['uparse'],
methods: {
wxParseImgTap(e) {
if (!this.preview) return;
const {
src
} = e.currentTarget.dataset;
if (!src) return;
this.uparse.preview(src, e);
},
// 图片视觉宽高计算函数区
wxParseImgLoad(e) {
const {
src
} = e.currentTarget.dataset;
if (!src) return;
const {
width,
height
} = e.mp.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 || imageWidth === '100%' ? '100%;' : `${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;
this.uparse.removeImageUrl(src);
this.preview = false;
}
// 判断按照那种方式进行缩放
if (originalWidth > windowWidth) {
// 在图片width大于手机屏幕width时候
results.imageWidth = '100%';
results.imageheight = (windowWidth * (originalHeight / originalWidth));
} else {
// 否则展示原来的数据
results.imageWidth = originalWidth;
results.imageheight = originalHeight;
}
return results;
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;// TODO currentTarget才有dataset
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
},
},
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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,
},
inject: ['uparse'],
methods: {
wxParseATap(e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
this.uparse.navigate(href, e);
}
}
};
</script>
<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>
/**
* 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 (name === 'align') {
node.styleStr = node.styleStr || '';
node.styleStr = node.styleStr += 'text-align:' + 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;
/**
*
* 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;
// HTML 支持的数学符号
function strNumDiscode(str) {
str = str.replace(/&forall;/g, '∀');
str = str.replace(/&part;/g, '∂');
str = str.replace(/&exist;/g, '∃');
str = str.replace(/&empty;/g, '∅');
str = str.replace(/&nabla;/g, '∇');
str = str.replace(/&isin;/g, '∈');
str = str.replace(/&notin;/g, '∉');
str = str.replace(/&ni;/g, '∋');
str = str.replace(/&prod;/g, '∏');
str = str.replace(/&sum;/g, '∑');
str = str.replace(/&minus;/g, '−');
str = str.replace(/&lowast;/g, '∗');
str = str.replace(/&radic;/g, '√');
str = str.replace(/&prop;/g, '∝');
str = str.replace(/&infin;/g, '∞');
str = str.replace(/&ang;/g, '∠');
str = str.replace(/&and;/g, '∧');
str = str.replace(/&or;/g, '∨');
str = str.replace(/&cap;/g, '∩');
str = str.replace(/&cup;/g, '∪');
str = str.replace(/&int;/g, '∫');
str = str.replace(/&there4;/g, '∴');
str = str.replace(/&sim;/g, '∼');
str = str.replace(/&cong;/g, '≅');
str = str.replace(/&asymp;/g, '≈');
str = str.replace(/&ne;/g, '≠');
str = str.replace(/&le;/g, '≤');
str = str.replace(/&ge;/g, '≥');
str = str.replace(/&sub;/g, '⊂');
str = str.replace(/&sup;/g, '⊃');
str = str.replace(/&nsub;/g, '⊄');
str = str.replace(/&sube;/g, '⊆');
str = str.replace(/&supe;/g, '⊇');
str = str.replace(/&oplus;/g, '⊕');
str = str.replace(/&otimes;/g, '⊗');
str = str.replace(/&perp;/g, '⊥');
str = str.replace(/&sdot;/g, '⋅');
return str;
}
// HTML 支持的希腊字母
function strGreeceDiscode(str) {
str = str.replace(/&Alpha;/g, 'Α');
str = str.replace(/&Beta;/g, 'Β');
str = str.replace(/&Gamma;/g, 'Γ');
str = str.replace(/&Delta;/g, 'Δ');
str = str.replace(/&Epsilon;/g, 'Ε');
str = str.replace(/&Zeta;/g, 'Ζ');
str = str.replace(/&Eta;/g, 'Η');
str = str.replace(/&Theta;/g, 'Θ');
str = str.replace(/&Iota;/g, 'Ι');
str = str.replace(/&Kappa;/g, 'Κ');
str = str.replace(/&Lambda;/g, 'Λ');
str = str.replace(/&Mu;/g, 'Μ');
str = str.replace(/&Nu;/g, 'Ν');
str = str.replace(/&Xi;/g, 'Ν');
str = str.replace(/&Omicron;/g, 'Ο');
str = str.replace(/&Pi;/g, 'Π');
str = str.replace(/&Rho;/g, 'Ρ');
str = str.replace(/&Sigma;/g, 'Σ');
str = str.replace(/&Tau;/g, 'Τ');
str = str.replace(/&Upsilon;/g, 'Υ');
str = str.replace(/&Phi;/g, 'Φ');
str = str.replace(/&Chi;/g, 'Χ');
str = str.replace(/&Psi;/g, 'Ψ');
str = str.replace(/&Omega;/g, 'Ω');
str = str.replace(/&alpha;/g, 'α');
str = str.replace(/&beta;/g, 'β');
str = str.replace(/&gamma;/g, 'γ');
str = str.replace(/&delta;/g, 'δ');
str = str.replace(/&epsilon;/g, 'ε');
str = str.replace(/&zeta;/g, 'ζ');
str = str.replace(/&eta;/g, 'η');
str = str.replace(/&theta;/g, 'θ');
str = str.replace(/&iota;/g, 'ι');
str = str.replace(/&kappa;/g, 'κ');
str = str.replace(/&lambda;/g, 'λ');
str = str.replace(/&mu;/g, 'μ');
str = str.replace(/&nu;/g, 'ν');
str = str.replace(/&xi;/g, 'ξ');
str = str.replace(/&omicron;/g, 'ο');
str = str.replace(/&pi;/g, 'π');
str = str.replace(/&rho;/g, 'ρ');
str = str.replace(/&sigmaf;/g, 'ς');
str = str.replace(/&sigma;/g, 'σ');
str = str.replace(/&tau;/g, 'τ');
str = str.replace(/&upsilon;/g, 'υ');
str = str.replace(/&phi;/g, 'φ');
str = str.replace(/&chi;/g, 'χ');
str = str.replace(/&psi;/g, 'ψ');
str = str.replace(/&omega;/g, 'ω');
str = str.replace(/&thetasym;/g, 'ϑ');
str = str.replace(/&upsih;/g, 'ϒ');
str = str.replace(/&piv;/g, 'ϖ');
str = str.replace(/&middot;/g, '·');
return str;
}
function strcharacterDiscode(str) {
// 加入常用解析
str = str.replace(/&nbsp;/g, ' ');
str = str.replace(/&ensp;/g, ' ');
str = str.replace(/&emsp;/g, ' ');
str = str.replace(/&quot;/g, "'");
str = str.replace(/&amp;/g, '&');
str = str.replace(/&lt;/g, '<');
str = str.replace(/&gt;/g, '>');
str = str.replace(/&#8226;/g, '•');
return str;
}
// HTML 支持的其他实体
function strOtherDiscode(str) {
str = str.replace(/&OElig;/g, 'Œ');
str = str.replace(/&oelig;/g, 'œ');
str = str.replace(/&Scaron;/g, 'Š');
str = str.replace(/&scaron;/g, 'š');
str = str.replace(/&Yuml;/g, 'Ÿ');
str = str.replace(/&fnof;/g, 'ƒ');
str = str.replace(/&circ;/g, 'ˆ');
str = str.replace(/&tilde;/g, '˜');
str = str.replace(/&ensp;/g, '');
str = str.replace(/&emsp;/g, '');
str = str.replace(/&thinsp;/g, '');
str = str.replace(/&zwnj;/g, '');
str = str.replace(/&zwj;/g, '');
str = str.replace(/&lrm;/g, '');
str = str.replace(/&rlm;/g, '');
str = str.replace(/&ndash;/g, '–');
str = str.replace(/&mdash;/g, '—');
str = str.replace(/&lsquo;/g, '‘');
str = str.replace(/&rsquo;/g, '’');
str = str.replace(/&sbquo;/g, '‚');
str = str.replace(/&ldquo;/g, '“');
str = str.replace(/&rdquo;/g, '”');
str = str.replace(/&bdquo;/g, '„');
str = str.replace(/&dagger;/g, '†');
str = str.replace(/&Dagger;/g, '‡');
str = str.replace(/&bull;/g, '•');
str = str.replace(/&hellip;/g, '…');
str = str.replace(/&permil;/g, '‰');
str = str.replace(/&prime;/g, '′');
str = str.replace(/&Prime;/g, '″');
str = str.replace(/&lsaquo;/g, '‹');
str = str.replace(/&rsaquo;/g, '›');
str = str.replace(/&oline;/g, '‾');
str = str.replace(/&euro;/g, '€');
str = str.replace(/&trade;/g, '™');
str = str.replace(/&larr;/g, '←');
str = str.replace(/&uarr;/g, '↑');
str = str.replace(/&rarr;/g, '→');
str = str.replace(/&darr;/g, '↓');
str = str.replace(/&harr;/g, '↔');
str = str.replace(/&crarr;/g, '↵');
str = str.replace(/&lceil;/g, '⌈');
str = str.replace(/&rceil;/g, '⌉');
str = str.replace(/&lfloor;/g, '⌊');
str = str.replace(/&rfloor;/g, '⌋');
str = str.replace(/&loz;/g, '◊');
str = str.replace(/&spades;/g, '♠');
str = str.replace(/&clubs;/g, '♣');
str = str.replace(/&hearts;/g, '♥');
str = str.replace(/&diams;/g, '♦');
str = str.replace(/&#39;/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,
};
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment