文件上传

This commit is contained in:
jia 2023-11-05 00:08:34 +08:00
commit 89ac8f2ab6
59 changed files with 8868 additions and 0 deletions

20
.hbuilderx/launch.json Normal file
View File

@ -0,0 +1,20 @@
{
// launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version" : "0.0",
"configurations" : [
{
"app-plus" : {
"launchtype" : "local"
},
"default" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"playground" : "custom",
"type" : "uni-app:app-android"
}
]
}

31
App.vue Normal file
View File

@ -0,0 +1,31 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
/*每个页面公共css */
* {
margin: 0;
padding: 0;
}
page {
background: #F3F4F8;
}
@import "static/css/base.css";
@import "static/css/style.scss";
@import url('static/iconfont/iconfont.css')
</style>

24
api/approve.js Normal file
View File

@ -0,0 +1,24 @@
import oahttp from "@/utils/oahttp.js";
/**
* 审批类型
*/
export const approveTypes = (data) => oahttp.get('/approve/approveType', data)
/**
* 审批列表
*/
export const approveLists = (data) => oahttp.get('/approve/lists', data)
/**
* 审批详情
*/
export const approveDetails = (data) => oahttp.post('/approve/detail', data)
/**
* 审批
*/
export const approveAudit = (data) => oahttp.post('/approve/audit', data)

12
api/business.js Normal file
View File

@ -0,0 +1,12 @@
import oahttp from "@/utils/oahttp.js";
/**
* 商机列表
*/
export const opportunity = (data) => oahttp.get('/information/list', data)
/**
* 商机详情
*/
export const oppordetails = (data) => oahttp.get('/information/details', data)

14
api/bussness.js Normal file
View File

@ -0,0 +1,14 @@
import oahttp from "@/utils/aa.js";
/**
* 绑定scoket
*/
export const bindScoket = (data) => oahttp.post('/common/im/doBindUid', data)
// 发送消息
export const sendMsgApi = (data) => oahttp.post('/common/im/sendTextMsg', data)
// 发送文件
export const sendFileApi = (data) => oahttp.post('/common/im/sendFileMsg', data)
// 消息列表
export const getMsgListApi = (data) => oahttp.post('/common/im/msgList', data)
// 片区经理id
export const getAreaManagerApi = (data) => oahttp.post('/common/im/getAreaManager', data)

77
api/company.js Normal file
View File

@ -0,0 +1,77 @@
import oahttp from "@/utils/oahttp.js";
/**
* 我的公司
*/
export const companyMine = (data) => oahttp.get('/company/mine', data)
/**
* 公司列表
*/
export const companyIndex = (data) => oahttp.get('/company/index', data)
/**
* 未签约公司列表
*/
export const companyUnsigned = (data) => oahttp.get('/company/unsigned', data)
/**
* 公司详情
*/
export const companyView = (data) => oahttp.get('/company/view', data)
/**
* 公司详情
*/
export const companyAreaManager = (data) => oahttp.get('/company/areaManager', data)
/**
* 人员列表
*/
export const companyUser = (data) => oahttp.get('/company/users', data)
/**
* 人员详情
*/
export const companyUserDetail = (data) => oahttp.get('/company/user', data)
/**
* 月流水
*/
export const accountMonthList = (data) => oahttp.get('/account_log/company_year_count', data)
/**
* 日流水
*/
export const accountDateList = (data) => oahttp.get('/account_log/company_lists', data)
/**
* 发起合同
*/
export const initiateContract = (data) => oahttp.post('/company/initiate_contract', data)
/**
* 生成合同
*/
export const Draftingcontracts = (data) => oahttp.post('/company/Draftingcontracts', data)
/**
* 发送短信
*/
export const postsms = (data) => oahttp.post('/company/postsms', data)
/**
* 公司财务
*/
export const sss = (data) => oahttp.post('/company/postsms', data)
/**
* 查询甲方公司信息
*/
export const getPartyACompany = (data) => oahttp.get('/company/getPartyACompany', data)
/**
* 查询押金凭证记录
*/
export const getDepositRechargeTransferVoucherList = (data) => oahttp.get('/company/getDepositRechargeTransferVoucherList', data)

7
api/complaint.js Normal file
View File

@ -0,0 +1,7 @@
import oahttp from "@/utils/oahttp.js";
/**
* 发起投诉
*/
export const complaintFeedback = (data) => oahttp.post('/company/complaint_feedback', data)

6
api/config.js Normal file
View File

@ -0,0 +1,6 @@
import oahttp from "@/utils/oahttp.js";
/**
* 获取配置信息
*/
export const getConfig = (data) => oahttp.get('/index/config', data, { noAuth:true }, true)

12
api/contract.js Normal file
View File

@ -0,0 +1,12 @@
import oahttp from "@/utils/oahttp.js";
/**
* ºÏͬÁбí
*/
export const contractList = (data) => oahttp.get('/contract/index', data)
/**
* ºÏͬÏêÇé
*/
export const contractView = (data) => oahttp.get('/contract/view', data)

50
api/file.js Normal file
View File

@ -0,0 +1,50 @@
import {
HTTP_REQUEST_URL_THREE,
HEADER,
TOKENNAME,
} from '@/config/app';
import {
Toast
} from '../libs/uniApi';
// import { checkLogin } from '../libs/login';
import store from '../store';
function toLogin() {
store.commit("LOGOUT");
uni.showToast({
title: '请登录',
icon: 'none',
duration: 1000
});
}
function upLoad(url, data) {
let Url = HTTP_REQUEST_URL_THREE,
header = {}
if (store.state.app.token) header[TOKENNAME] = store.state.app.token;
return new Promise((reslove, reject) => {
uni.uploadFile({
url: Url + '/api' + url,
filePath: data.filePath,
name: data.name,
success: (uploadFileRes) => {
uploadFileRes.data = JSON.parse(uploadFileRes.data)
if (uploadFileRes.data.code == 1) reslove(uploadFileRes.data)
else Toast('网络错误')
},
fail: (err) => {
Toast('网络错误')
}
})
});
}
export const upLoadImage = (data) => {
return upLoad('/upload/image', data)
}
export const VIDEO_URL = HTTP_REQUEST_URL_THREE + '/api/upload/video'
export const FILE_URL = HTTP_REQUEST_URL_THREE + '/api/home_index/upload'
// im文件上传
// export const VIDEO_URL_IM = HTTP_REQUEST_URL_THREE + '/api/upload/video'
export const FILE_URL_IM = HTTP_REQUEST_URL_THREE + '/common/im/sendFileMsg'

28
api/index.js Normal file
View File

@ -0,0 +1,28 @@
// let Token = localStorage.getItem("token")
let Token = uni.getStorageSync("token")
let request = (METHOD, URL, DATA) => {
return new Promise((reslove, reject) => {
uni.request({
url: 'https://ceshi-im.lihaink.cn/' + URL,
method: METHOD,
data: {
...DATA
},
header: {
'content-type': 'application/json',
"Authorization": Token || ""
},
success: function(res) {
reslove(res)
},
fail: function(err) {
reject(err)
},
});
})
}
export default request;

22
api/information.js Normal file
View File

@ -0,0 +1,22 @@
import oahttp from "@/utils/oahttp.js";
/**
* 新增档案
*/
export const informationAdd = (data) => oahttp.post('/information/add', data)
/**
* 新增列表
*/
export const informationList = (data) => oahttp.get('/information/list', data)
/**
* 档案详情
*/
export const informationDetails = (data) => oahttp.get('/information/details', data)
/**
* 更新商机
*/
export const informationOpportunityUpdate = (data) => oahttp.post('/information/opportunity_update', data)

3
api/junziqian.js Normal file
View File

@ -0,0 +1,3 @@
import oahttp from "@/utils/oahttp.js";
//获取合同链接
export const download_file = (data) => oahttp.get('/junziqian/download_file', data)

16
api/logistics.js Normal file
View File

@ -0,0 +1,16 @@
import oahttp from "@/utils/logistics.js";
/**
* 订单列表
*/
export const getList = (data) => oahttp.get('/courierLstData', data)
// 订单详情
export const getDetil = (data) => oahttp.get('/lstDetail', data)
// 取货
export const takeGoods = (data) => oahttp.post('/takeGoods', data)
// 送达
export const doneDelivery = (data) => oahttp.post('/doneDelivery', data)
/**
* 更新商机
*/
export const informationOpportunityUpdate = (data) => oahttp.post('/information/opportunity_update', data)

7
api/notice.js Normal file
View File

@ -0,0 +1,7 @@
import oahttp from "@/utils/oahttp.js";
/**
* 公告列表
*/
export const noticeList = (data) => oahttp.get('/article/lists', data)
export const noticeDetail = (data) => oahttp.get('/article/detail', data)

247
api/oa.js Normal file
View File

@ -0,0 +1,247 @@
import oahttp from "@/utils/oahttp.js";
//获取代办事项 已处理事项
export const getMatters = (data) => oahttp.get('/approve/list', data, { noAuth: true })
//获取任务列表
export const getTaskListApi = (data) => oahttp.get('/task/list', data)
//获取 我发起的审批
export const getExamineListApi = () => oahttp.get('/approve/my_list')
//获取工资详情信息
export const getSalaryDeatilsApi = () => oahttp.get('/user/info')
//获取部门
export const getDepartmentApi = () => oahttp.get('/index/get_department_tree')
//获取部门人员
export const getDepartmentPersonApi = (data) => oahttp.get('/index/get_employee', data)
//新建任务
export const addNewTaskApi = (data) => oahttp.post('/task/add', data)
//获取文档列表
export const getDocumentListApi = (data) => oahttp.get('/note_index/index', data)
//获取文档列表
export const getDocumentListnote = (data) => oahttp.get('/note_index/view', data)
//获取个人信息
export const getPersonInfoApi = () => oahttp.get('/home_index/userinfo')
//获取应用
export const oaapprove = () => oahttp.get('/oa_approve/app')
//获取部门
export const userdepartment = (data) => oahttp.get('/user_department/index',data)
//获取部门架构
export const userdepartmenttree = () => oahttp.get('/user_department/tree')
//用户信息统计
export const getdatatotal = (data) => oahttp.get('/home_index/data_total',data)
//新增部门
export const adddepartment = (data) => oahttp.post('/user_department/add',data)
//删除部门
export const deletedepartment = (data) => oahttp.post('/user_department/delete',data)
//获取岗位
export const userposition = (data) => oahttp.get('/user_position/index',data)
//获取岗位权限组
export const userpositiongroup = (data) => oahttp.get('/user_position/group',data)
//新增编辑岗位
export const adduserposition= (data) => oahttp.post('/user_position/add',data)
//删除岗位
export const deleteuserposition = (data) => oahttp.post('/user_position/delete',data)
//获取人事调动记录
export const userpersonal = (data) => oahttp.get('/user_personal/change',data)
//新增编辑人事调动记录
export const adduserpersonal= (data) => oahttp.post('/user_personal/change_add',data)
//获取部门树形架构
export const getdepartmenttree = (data) => oahttp.get('/common/get_department_tree',data)
//获取部门员工
export const getemployee = (data) => oahttp.get('/common/get_employee',data)
//获取离职信息
export const leaveuserpersonal = (data) => oahttp.get('/user_personal/leave',data)
//删除离职恢复职务
export const leavedelete = (data) => oahttp.get('/user_personal/leave_delete',data)
//新增编辑离职
export const leaveadd = (data) => oahttp.get('/user_personal/leave_add',data)
//获取企业员工列表
export const comanyerlist = (data) => oahttp.get('/user_user/index',data)
//获取企业员工详情
export const comanyerview= (data) => oahttp.get('/user_user/view',data)
//新增编辑员工
export const addcomanyer= (data) => oahttp.post('/user_user/add',data)
//设置员工状态
export const setcomanyer= (data) => oahttp.get('/user_user/set',data)
//获取文章列表
export const articleindex= (data) => oahttp.get('/article_index/index',data)
//获取文章详情
export const articleview= (data) => oahttp.get('/article_index/view',data)
//获取项目列表
export const projectlist = (data) => oahttp.get('/project_index/index',data)
//新增项目
export const addproject= (data) => oahttp.post('/project_index/add',data)
//获取项目列表详情
export const projectview= (data) => oahttp.get('/project_index/view',data)
//删除附件
export const deleteprojectview= (data) => oahttp.post('/project_index/delete',data)
//上传项目附件
export const addfile= (data) => oahttp.post('/project_index/add_file',data)
//删除附件
export const deletefile= (data) => oahttp.post('/project_index/delete_file',data)
//上传项目附件
export const addlink= (data) => oahttp.post('/project_index/add_link',data)
//删除附件
export const deletelink= (data) => oahttp.post('/project_index/delete_link',data)
//获取项目任务列表
export const projecttasklist = (data) => oahttp.get('/project_task/index',data)
//新增项目任务
export const addprojecttask= (data) => oahttp.post('/project_task/add',data)
//获取项目任务列表详情
export const projecttaskview= (data) => oahttp.get('/project_task/view',data)
//删除项目任务列表
export const deleteproject_task= (data) => oahttp.post('/project_task/delete',data)
//获取项目工时列表
export const schedulelist = (data) => oahttp.get('/project_task/task_time',data)
//新增项目工时
export const addschedule= (data) => oahttp.post('/oa_schedule/add',data)
//删除项目工时列表
export const deleteschedule= (data) => oahttp.post('/oa_schedule/delete',data)
//获取获取审批应用字段
export const appfield = (data) => oahttp.get('/oa_approve/app_field',data)
//发起审批
export const appapprove = (data) => oahttp.post('/oa_approve/add',data)
//获取发起审批记录
export const approveindex = (data) => oahttp.get('/oa_approve/index',data)
//获取我处理的审批记录
export const approvelist = (data) => oahttp.get('/oa_approve/list',data)
//获取抄送的审批记录
export const approvecopy = (data) => oahttp.get('/oa_approve/copy',data)
//获取审批消息
export const appmessageinbox = (data) => oahttp.get('/message_index/inbox',data)
//获取审批消息
export const appmessageread = (data) => oahttp.get('/message_index/read',data)
//流程审批
export const appflow_check = (data) => oahttp.post('/oa_approve/flow_check',data)
//获取审批消息
export const appapproveview= (data) => oahttp.get('/oa_approve/view',data)
//撤回审批
export const appapflow_check= (data) => oahttp.post('/index/flow_check',data)
//获取发起报销记录
export const appexpenseindex = (data) => oahttp.get('/finance_expense/index',data)
//获取我处理的报销记录
export const apexpenselist = (data) => oahttp.get('/finance_expense/list',data)
//获取抄送的报销记录
export const appexpensecopy = (data) => oahttp.get('/oa_approve/copy',data)
//报销类型
export const appexpensecate = (data) => oahttp.get('/common/get_expense_cate',data)
//报销审批流程id
export const appexpenseflow = (data) => oahttp.get('/finance_expense/get_expense_flow',data)
//发起报销
export const appexpense = (data) => oahttp.post('/finance_expense/add',data)
//删除报销报销流程详情
export const deleteexpenseflow = (data) => oahttp.get('/finance_expense/delete',data)
//获取报销流程详情
export const appexpenseview = (data) => oahttp.get('/finance_expense/view',data)
//报销打款
export const topayview = (data) => oahttp.get('/finance_expense/topay',data)
//获取报销打款
export const checkedlist = (data) => oahttp.get('/finance_expense/checkedlist',data)
//发票
//我申请的发票
export const invoiceindex = (data) => oahttp.get('/finance_invoice/index',data)
//我处理的发票
export const invoicelist = (data) => oahttp.get('/finance_invoice/list',data)
//抄送给我的发票
export const invoicecopy = (data) => oahttp.get('/finance_invoice/copy',data)
//获取发票类型
export const invoicecate = (data) => oahttp.get('/common/get_invoice_subject',data)
//发起发票
export const addinvoice = (data) => oahttp.post('/finance_invoice/add',data)
//获取发票流程详情
export const invoiceview = (data) => oahttp.get('/finance_invoice/view',data)
//获取发票流程
export const invoiceflow = (data) => oahttp.get('/finance_invoice/get_invoice_flow',data)
//获取待办事项
export const todosubjec = (data) => oahttp.get('/common/get_todo_subject',data)
//获取待办事任务
export const tasksubjec = (data) => oahttp.get('/common/get_task_list',data)
//获取发票开票
export const invoicecheckedlist = (data) => oahttp.get('/finance_invoice/checkedlist',data)
//发票开票/修改
export const financeopen = (data) => oahttp.get('/finance_invoice/open',data)
//发票作废
export const tovoid = (data) => oahttp.post('/finance_invoice/tovoid',data)
//发票反作废
export const novoid = (data) => oahttp.get('/finance_invoice/novoid',data)
//获取发票到账信息
export const incomeflow = (data) => oahttp.get('/finance_income/index',data)
//获取发票到账详情
export const incomeview = (data) => oahttp.get('/finance_income/view',data)

60
api/oaApi.js Normal file
View File

@ -0,0 +1,60 @@
import oahttp from "@/utils/oahttp.js";
/**
* 获取代办事项 已处理事项
*/
export const getIndexListAPI = (data) => oahttp.get('/index/list', data)
/**
* 获取任务列表
*/
export const getTaskListAPI = (data) => oahttp.get('/task/list', data)
/**
* 获取我的任务
*/
export const getMyTaskListAPI = (data) => oahttp.get('/task/datalist', data)
/**
* 获取任务详情
*/
export const getTaskDetailsAPI = (data) => oahttp.get('/task/read', data)
/**
* 我发起的审批
*/
export const getApproveMyListAPI = (data) => oahttp.get('/approve/my_list', data)
/**
* 我审批的
*/
export const getHandleListAPI = (data) => oahttp.get('/approve/handle_list', data)
/**
* 抄送给我的
*/
export const getCopyOfMyListAPI = (data) => oahttp.get('/approve/copy', data)
/*
* 待办事项
*/
export const getApproveListAPI = (data) => oahttp.get('/approve/list', data)
/**
* 获取个人中心数据
*/
export const getUserIndexAPI = (data) => oahttp.get('/user/index', data)
/**
* 保存个人信息修改
*/
export const PostUserPerSubmitAPI = (data) => oahttp.post('/home_index/edit_personal', data)
/**
* 获取审核流程
* index/get_flow?type=1
*/
export const getFlowAPI = (data) => oahttp.get('/index/get_flow', data)
/**
* 获取审核步骤人员
*/
export const getFlowUsersAPI = (data) => oahttp.get('/index/get_flow_users', data, { noVerify: true })
/** 获取部门树形节点列表 */
export const getDepartmentTreeAPI = () => oahttp.get('/index/get_department_tree')
/** 获取某个部门的员工 */
export const getEmployeeAPI = (data) => oahttp.get('/index/get_employee', data)
/** 发起审批 */
export const PostApproveAddAPI = (data) => oahttp.post('/approve/add', data)

47
api/oaPbulic.js Normal file
View File

@ -0,0 +1,47 @@
import oahttp from "@/utils/oahttp.js";
/**
* 获取市
*/
export const commonCity = (data) => oahttp.get('/common/city', data)
/**
* 获取省
*/
export const commonProvince = (data) => oahttp.get('/common/province', data)
/**
* 获取区县
*/
export const commonArea = (data) => oahttp.get('/common/area', data)
/**
* 获取城镇
*/
export const commonStreet = (data) => oahttp.get('/common/street', data)
/**
* 获取村
*/
export const commonVillage = (data) => oahttp.get('/common/village', data)
/**
* 获取小队
*/
export const commonBrigade = (data) => oahttp.get('/common/brigade', data)
/**
* 获取商机分类
*/
export const categoryBusinessList = (data) => oahttp.get('/CategoryBusiness/list', data)
/**
* 字典列表
*/
export const dictDataLists = (data) => oahttp.get('/common/dict_data_lists', data)
/**
* 字典列表: 按数据值取
*/
export const dictDataListsTypeValue = (data) => oahttp.get('/common/dict_data_lists_by_type_value', data)

71
api/oaUser.js Normal file
View File

@ -0,0 +1,71 @@
import oahttp from "@/utils/oahttp.js";
/**
* 登录
*/
export const loginAccount = (data, onReLogin = false) => oahttp.post('/home_login/login_submit', data, { noAuth: true, onReLogin: onReLogin })
/**
* cesi
*/
export const test = (data) => oahttp.post('/index/config', data, { noAuth: true })
/**
* 个人中心
*/
export const userCenter = (data) => oahttp.get('/user/center', data)
/**
* 个人信息
*/
export const userInfo = (data) => oahttp.get('/home_index/userinfo', data)
/**
* 修改密码
*/
export const changePassword = (data) => oahttp.post('/home_index/edit_password', data)
/**
* 获取当前公司已创建的小队
*/
export const userCompanyBrigade = (data) => oahttp.get('/user/company_brigade', data)
/**
* 新增人员
*/
export const loginAdd = (data) => oahttp.post('/login/add', data)
/**
* 修改人员
*/
export const userSetInfo = (data) => oahttp.post('/user/setInfo', data)
/**
* 设置是否为队长
*/
export const loginSetInfo = (data) => oahttp.post('/login/setInfo', data)
/**
* 生成合同
*/
export const userDraftingcontracts = (data) => oahttp.post('/user/Draftingcontracts', data)
/**
* 发起合同
*/
export const userInitiateContract = (data) => oahttp.post('/user/initiate_contract', data)
/**
* 发送短信
*/
export const userPostsms = (data) => oahttp.post('/user/postsms', data)
/**
* 注销账号
*/
export const destroyAccount = (data) => oahttp.post('/user/destroy_account', data)
/**
* 商城登录
*/
export const loginShopAccount = (data) => oahttp.post('/login/shop_account', data, { noAuth: true })

59
api/pay.js Normal file
View File

@ -0,0 +1,59 @@
import oahttp from "@/utils/oahttp.js";
/**
* 充值
*/
export const recharge = (data) => oahttp.post('/recharge/recharge', data)
/**
* 押金充值记录
*/
export const deposit_recharge = (data) => oahttp.get('/recharge/deposit_lists', data)
/**
* 支付方式
*/
export const payWay = (data) => oahttp.get('/pay/payWay', data)
/**
* 预支付
*/
export const payPrepay = (data) => oahttp.post('/pay/prepay', data)
/**
* 支付配置
*/
export const wechatJsConfig = (data) => oahttp.get('/wechat/jsConfig', data)
/**
* 支付状态
*/
export const payStatus = (data) => oahttp.get('/pay/payStatus', data)
/**
* 充值记录
*/
export const rechargeLists = (data) => oahttp.get('/recharge/lists', data)
/**
* 余额明细
*/
export const accountLogLists = (data) => oahttp.get('/account_log/lists', data)
/**
* 月份统计
*/
export const accountLogListsMonth = (data) => oahttp.get('/account_log/year_count', data)
/**
* 余额提现
*/
export const userWithdraw = (data) => oahttp.get('/user/withdraw', data)
/**
* 提现记录
*/
export const userWithdrawList = (data) => oahttp.get('/user/withdrawList', data)
/**
* 可提现金额
*/
export const getCurrCycleWithdraw = (data) => oahttp.get('/user/getCurrCycleWithdraw', data)

53
api/property.js Normal file
View File

@ -0,0 +1,53 @@
import oahttp from "@/utils/oahttp.js";
// http://logistics.lihaink.cn/api/getCarHistory
/**
* 车辆列表
*/
// /api/vehicle/townCompanyVehicleIndex
export const getvehicleListApi = (data) => oahttp.get('/vehicle/townCompanyVehicleIndex', data)
// 车辆详情
export const getvehicleDetailApi = (data) => oahttp.get('/vehicle/vehicleInfo', data)
// 车辆上传
export const upVehicleApi = (data) => oahttp.post('/vehicle/rentApply', data)
// 申请用车
export const applycarApi = (data) => oahttp.post('/vehicle/rentApply', data)
// 显示轨迹
export const locusApi = (data) => oahttp.post('/vehicle/vehicleTrack', data)
// 获取可购买车辆列表
export const canBuyCarListApi = (data) => oahttp.get('/vehicle/getFreeCars', data)
// 购买车辆
export const buyCarApi = (data) => oahttp.post('/vehicle/buyCars', data)
// 当前车辆位置信息
// export const locusApi = (data) => oahttp.post('/vehicle/vehicleTrack', data)
// api / getCarLocal
// 签约列表
export const getAgencyListApi = (data) => oahttp.get('/vehicle/rentApplyList', data)
// 签约公司详情
export const getAgencyDetailApi = (data) => oahttp.get('/vehicle/rentApplyInfo', data)
// 车辆租赁
export const leaseApi = (data) => oahttp.post('/vehicle/setContractByTownCompany', data)
// 生成合同
export const contractApi = (data) => oahttp.post('/vehicle/setContractByVillageCompany', data)
// 发送合同
export const sendcontractApi = (data) => oahttp.post('/vehicle/initiatingRentCarContract', data)
// 申请驳回
export const overruleApi = (data) => oahttp.post('/vehicle/rejectRentApply', data)
// 小组公司详情
export const villageCompanyApi = (data) => oahttp.get('/vehicle/villageCompanyIndex', data)
// 重新发送短信
export const sendMsgApi = (data) => oahttp.post('/vehicle/sendSmsAgain', data)
// 解约
export const cancelContractApi = (data) => oahttp.post('/vehicle/cancelContract', data)
// 镇街公司合同列表
export const ContractListApi = (data) => oahttp.get('/vehicle/townCompanyContractList', data)
// 图片上传
export const upLoadImage = (data) => oahttp.post('/upload/image', data)
// 资产详情
// export const getpropertyDetil = (data) => oahttp.get('/lstDetail', data)
/**
* 更新商机
*/
// export const informationOpportunityUpdate = (data) => oahttp.post('/information/opportunity_update', data)

17
api/pubic.js Normal file
View File

@ -0,0 +1,17 @@
import request from '@/utils/request.js'
export function commonAuth(data) {
return request.post(
"auth", data, {
noAuth: true
}
);
}
/**
* 小程序用户登录
* @param data object 小程序用户登陆信息
*/
export function login(data) {
return request.post("auth/mp", data, {
noAuth: true
});
}

21
api/shareholder.js Normal file
View File

@ -0,0 +1,21 @@
import oahttp from "@/utils/oahttp.js";
/**
* 股金流水
*/
export const companyAccountLog = (data) => oahttp.get('/company_account_log/lists', data)
/**
* 股金详情
*/
export const companyShareholderInfo = (data) => oahttp.get('/company/shareholder_info', data)
/**
* 发起合同
*/
export const initiateShareholderContract = (data) => oahttp.post('/company/initiate_shareholder_contract', data)
/**
* 上交股金
*/
export const companyPayShareCapital = (data) => oahttp.post('/company/pay_share_capital', data)

62
api/task.js Normal file
View File

@ -0,0 +1,62 @@
import oahttp from "@/utils/oahttp.js";
/**
* 任务列表
*/
export const taskLists = (data) => oahttp.get('/task/lists', data)
/**
* 任务:更新档案列表
*/
export const taskInformationgist = (data) => oahttp.get('/task/informationg_list', data)
/**
* 任务:片区交易
*/
export const taskOrderDetail = (data) => oahttp.get('/task/order_detail', data)
/**
* 任务:三轮游走获取地址
*/
export const taskTricycleDetail = (data) => oahttp.get('/task/tricycle_detail', data)
/**
* 任务:三轮游走上传位置
*/
export const taskAddTricycleCoordinate = (data) => oahttp.post('/task/add_tricycle_coordinate', data)
/**
* 任务:入股详情
*/
export const taskShareholder = (data) => oahttp.get('/task/shareholder', data)
/**
* 任务:其他任务详情
*/
export const taskOtherTaskDetail = (data) => oahttp.get('/task/other_task_detail', data)
/**
* 任务:提交其他任务
*/
export const taskOtherTaskCommit = (data) => oahttp.post('/task/commit_other_task', data)
/**
* 任务:服务任务详情
*/
export const townTaskDetails = (data) => oahttp.get('/task/service_task_detail', data)
/**
* 任务:提交督促小组服务团队学习任务
*/
export const serviceTask4Commit = (data) => oahttp.post('/task/commit_town_task_type4', data)
/**
* 任务:数字农贸宣传加工业务建设和招商任务详情
*/
export const marketTask10Detail = (data) => oahttp.post('/task/town_task_type_marketing_director_10_detail', data)
/**
* 任务:数字农贸宣传加工业务建设和招商任务提交
*/
export const marketTask10Commit = (data) => oahttp.post('/task/commit_town_task_type_marketing_director_10', data)

65
api/upload.js Normal file
View File

@ -0,0 +1,65 @@
// import base from "@/config/baseUrl";
// let baseUrl = 'https://ceshi.excellentkk.cn/api';
import store from '../store';
import { HTTP_REQUEST_URL_TWO, HTTP_REQUEST_URL_THREE, HEADER } from '@/config/app';
let header = HEADER;
if (store.state.app.token){
header.token = store.state.app.token;
}
function uploads(src, type) {
return new Promise((resolve, reject) => {
// console.log('上传', type === 'img' ? '图片' : '视频', '', src)
let a = uni.uploadFile({
// url: base.baseUrl + '/upload?token=',
url: HTTP_REQUEST_URL_TWO + '/api' + '/upload?token=',
filePath: src,
name: 'file',
success: (res) => {
let data = JSON.parse(res.data)
if (data.code != 1) {
uni.$u.toast(data.msg)
return false
} else {
resolve(data.data.url) // 返回线上地址
}
},
fail: (err) => {
reject(err)
console.log('upload-上传失败', err)
}
});
})
}
function oaUploads(src, type) {
return new Promise((resolve, reject) => {
// console.log('上传', type === 'img' ? '图片' : '视频', '', src)
let a = uni.uploadFile({
url: HTTP_REQUEST_URL_THREE + '/api/home_index/upload',
filePath: src,
name: 'file',
header: header,
success: (res) => {
let data = JSON.parse(res.data)
if (data.code == 0) {
resolve(data.data) // 返回线上地址
} else {
uni.$u.toast(data.msg)
return false
}
},
fail: (err) => {
reject(err)
console.log('upload-上传失败', err)
}
});
})
}
export {
uploads,
oaUploads
}

743
api/user.js Normal file
View File

@ -0,0 +1,743 @@
import request from "@/utils/request.js";
import Cache from '@/utils/cache'
import http from "@/utils/http.js";
/**
* 获取后台账号密码
*/
export const getBackstageAPI = (data) => http.get('/User/get_backstage', data)
// 获取已录入公司
export const getEnterListMsgAPI = (data) => http.get('/enter/list', data)
// 录入公司
export const postEntercompanyAPI = (data) => request.post('entercompany', data)
// 获取地址
export const getSiteAPI = (data) => http.get('/User/index', data)
export const getShimingAPI = (data) => http.get('/User/get_shiming', data)
export const postRealnameAPI = (data) => http.post('/User/realname', data)
/**
* 获取用户信息
*
*/
export function getUserInfo() {
return request.get('user');
}
/**
* 头像
*
*/
export function editAvatar(data) {
return request.post('user/change/info', data);
}
// 修改昵称
export function updateInfo(data) {
return request.post('user/change/avatar', data);
}
/**
* h5用户登录
* @param data object 用户账号密码
*/
export function loginH5(data) {
return request.post("auth/login", data, {
noAuth: true
});
}
/**
* h5用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMobile(data) {
return request.post("auth/smslogin", data, {
noAuth: true
});
}
/**
* h5用户手机号登录
* @param data object 用户手机号 也只能
*/
export function loginMpPhone(data) {
return request.post("auth/mp_phone", data, {
noAuth: true
});
}
/**
* 验证码key
*/
export function getCodeApi() {
return request.get("verify_code", {}, {
noAuth: true
});
}
/**
* h5用户发送验证码
* @param data object 用户手机号
*/
export function registerVerify(data) {
return request.post("auth/verify", data, {
noAuth: true
});
}
/**
* h5用户手机号注册
* @param data object 用户手机号 验证码 密码
*/
export function register(data) {
return request.post("auth/register", data, {
noAuth: true
});
}
/**
* 用户手机号修改密码
* @param data object 用户手机号 验证码 密码
*/
export function registerReset(data) {
return request.post("/register/reset", data, {
noAuth: true
});
}
/**
* 用户手机号忘记密码
*/
export function registerForget(data) {
return request.post("user/change_pwd", data, {
noAuth: true
});
}
/**
* 获取用户中心菜单
*
*/
export function getMenuList() {
return request.get("common/menus", {}, {
noAuth: true
});
}
/*
* 签到用户信息
* */
export function getSignUser() {
return request.get("user/sign/info");
}
/**
* 获取签到配置
*
*/
export function getSignConfig() {
return request.get('sign/config')
}
/**
* 获取签到列表
* @param object data
*/
export function getSignList(data) {
return request.get('user/sign/lst', data);
}
/**
* 用户签到
*/
export function setSignIntegral() {
return request.post('user/sign/create')
}
/**
* 签到列表(年月)
* @param object data
*
*/
export function getSignMonthList(data) {
return request.get('user/sign/month', data)
}
/**
* 活动状态
*
*/
export function userActivity() {
return request.get('user/activity');
}
/*
* 资金明细types|0=全部,1=消费,2=充值,3=返佣
* */
export function getCommissionInfo(q, types) {
return request.get("user/bill", q);
}
/*
* 提现列表
* */
export function extractLst(data) {
return request.get("user/extract/lst", data);
}
/*
* 积分记录
* */
export function getIntegralList(data) {
return request.get("user/integral/lst", data);
}
/**
* 获取分销海报图片
*
*/
export function spreadBanner() {
//#ifdef H5
return request.get('user/spread_image', {
type: 'wechat'
});
//#endif
//#ifdef MP
return request.get('user/spread_image', {
type: 'routine'
});
//#endif
}
/**
*
* 获取推广用户一级和二级
* @param object data
*/
export function spreadPeople(data) {
return request.get('user/spread_list', data);
}
/**
*
* 推广佣金/提现总和
* @param int type
*/
export function spreadCount(type) {
return request.get('spread/count/' + type);
}
/*
* 推广数据
* */
export function getSpreadInfo() {
return request.get("/commission");
}
/**
*
* 推广订单
* @param object data
*/
export function spreadOrder(data) {
return request.get('user/spread_order', data);
}
/*
* 获取推广人排行
* */
export function getRankList(data) {
return request.get("user/spread_top", data);
}
/*
* 获取佣金排名
* */
export function getBrokerageRank(q) {
return request.get("user/brokerage_top", q);
}
/**
* 提现申请
* @param object data
*/
export function extractCash(data) {
return request.post('user/extract/create', data)
}
/**
* 提现银行/提现最低金额
*
*/
export function extractBank() {
return request.get('user/extract/banklst');
}
/**
* 会员等级列表
*
*/
export function userLevelGrade() {
return request.get('user/level/grade');
}
/**
* 获取某个等级任务
* @param int id 任务id
*/
export function userLevelTask(id) {
return request.get('user/level/task/' + id);
}
/**
* 检查用户是否可以成为会员
*
*/
export function userLevelDetection() {
return request.get('user/level/detection');
}
/**
*
* 地址列表
* @param object data
*/
export function getAddressList(data) {
return request.get('user/address/lst', data);
}
/**
* 设置默认地址
* @param int id
*/
export function setAddressDefault(id) {
return request.post('user/address/update/' + id)
}
/**
* 修改 添加地址
* @param object data
*/
export function editAddress(data) {
return request.post('user/address/create', data);
}
/**
* 删除地址
* @param int id
*
*/
export function delAddress(id) {
return request.post('user/address/delete/' + id)
}
/**
* 获取单个地址
* @param int id
*/
export function getAddressDetail(id) {
return request.get('user/address/detail/' + id);
}
/**
* 修改用户信息
* @param object
*/
export function userEdit(data) {
return request.post('user/edit', data);
}
/*
* 退出登录
* */
export function getLogout() {
return request.post("logout");
}
/**
* 佣金转入
*
*/
export function rechargeBrokerage(data) {
return request.post('user/recharge/brokerage', data)
}
/**
* 小程序充值
*
*/
export function rechargeRoutine(data) {
return request.post('recharge/routine', data)
}
/*
* 公众号充值
* */
export function rechargeWechat(data) {
return request.post("user/recharge", data);
}
/**
* 获取默认地址
*
*/
export function getAddressDefault() {
return request.get('address/default');
}
/**
* 充值金额选择
*/
export function getRechargeApi() {
return request.get("common/recharge_quota");
}
/**
* 登陆记录
*/
export function setVisit(data) {
return request.post('user/set_visit', {
...data
}, {
noAuth: true
});
}
/**
* 客服列表
*/
export function serviceList(data) {
return request.get("service/list", data);
}
/**
* 客服列表
*/
export function serviceLogin(key, data) {
return request.post("service/scan_login/" + key, data);
}
/**
* 客服获取客户列表
*/
export function serviceUserList(mer_id, data) {
return request.get("service/user_list/" + mer_id, data);
}
/**
* 用户获取聊天记录详情
*/
export function getChatRecord(to_uid, data) {
return request.get("service/history/" + to_uid, data);
}
/**
* 客服获取聊天记录详情
*/
export function getMerHistory(userid, mer_id, data) {
return request.get("service/mer_history/" + mer_id + '/' + userid, data);
}
/**
* 静默绑定推广人
* @param {Object} puid
*/
export function spread(puid) {
Cache.set("spread", puid || 0);
return request.post("user/spread", {
spread_spid: puid
});
}
/**
* 反馈类型
*/
export function feedbackType() {
return request.get("common/feedback_type");
}
/**
* 提交反馈
*/
export function feedback(data) {
return request.post("user/feedback", {
...data
});
}
/**
* 反馈列表
*/
export function feedbackList(data) {
return request.get("user/feedback/list", data);
}
/**
* 反馈列表
*/
export function feedbackDetail(id) {
return request.get("user/feedback/detail/" + id);
}
/**
* 浏览记录
*/
export function historyList(data) {
return request.get("user/history", data);
}
/**
* 删除浏览记录
*/
export function historyDelete(id) {
return request.post("user/history/delete/" + id);
}
/**
* 批量删除浏览记录
*/
export function historyBatchDelete(data) {
return request.post("user/history/batch/delete", data);
}
/**
* 批量收藏浏览记录
*/
export function historyBatchCollect(data) {
return request.post("user/relation/batch/create", data);
}
/**
* 佣金记录
*/
export function brokerage_list(data) {
return request.get("user/brokerage_list", data);
}
/**
* 佣金数据
*/
export function spreadInfo(data) {
return request.get("user/spread_info", data);
}
// 图片验证码
export function getCaptcha() {
return request.get('captcha', {}, {
noAuth: true
});
}
// 用户账户列表
export function userAcc() {
return request.get('user/account', {}, {
noAuth: true
});
}
// 创建发票
export function invoiceSave(data) {
return request.post('user/receipt/create', data);
}
// 编辑发票
export function invoiceUpdate(id, data) {
return request.post('user/receipt/update/' + id, data);
}
// 获取默认发票
export function invoiceDefault(id) {
return request.post('user/receipt/is_default/' + id);
}
// 发票抬头--列表
export function invoice(data) {
return request.get('user/receipt/lst', data);
}
// 发票抬头--删除
export function invoiceDelete(id) {
return request.post('user/receipt/delete/' + id);
}
// 发票--详情
export function invoiceDetail(id) {
return request.get('user/receipt/detail/' + id);
}
/**
* 新版分享海报信息获取
*
*/
export function spreadMsg(data) {
return request.get('user/v2/spread_image', data);
}
/**
* 图片链接转base64
*
*/
export function imgToBase(data) {
return request.post('common/base64', data);
}
/**
* 获取协议
*
*/
export function getAgreementApi(key) {
return request.get('agreement/' + key, {}, {
noAuth: true
});
}
/**
* 获取协议
*
*/
export function getIntegralInfo() {
return request.get('user/integral/info');
}
/**
* 获取店铺列表
*
*/
export function getStoreList(data) {
return request.get('user/services', data);
}
/*
获取佣金说明
*/
export function commissionDescription() {
return request.get('agreement/sys_extension_agree')
}
/*
获取用户分销等级信息
*/
export function getBrokerageInfo() {
return request.get('user/brokerage/info')
}
/*
获取用户分销等级表格数据
*/
export function getBrokerageGrade() {
return request.get('user/brokerage/all')
}
/*
分销员升级提醒
*/
export function brokerageNotice(data) {
return request.get(`user/brokerage/notice`, data)
}
/*
口令解析
*/
export function pwdResolution(data) {
return request.get(`command/copy?key=${data}`)
}
/*
获取佣金说明
*/
export function getInstructions(key) {
return request.get(`agreement/${key}`)
}
/*
会员信息
*/
export function memberInfo() {
return request.get('user/member/info')
}
/**
* 成长值记录
* @param object data
*
*/
export function growthValueRecord(data) {
return request.get('user/member/log', data)
}
/**
* 协议规则列表
* @param object data
*
*/
export function cacheLst() {
return request.get('agreement_lst', {}, {
noAuth: true
})
}
/**
* 协议规则列表对应的数据
* @param object data
*
*/
export function cacheInfo(key) {
return request.get(`agreement/${key}`, {}, {
noAuth: true
})
}
/**
* 注销账户
* @param object data
*
*/
export function userOut(data) {
return request.post(`user/cancel`, data)
}
/**
* 获取聊天用户信息
* @param object data
*
*/
export function serviceUser(merId, uid) {
return request.get(`service/user/${merId}/${uid}`)
}
/**
* 保存聊天用户备注
* @param object data
*
*/
export function serviceSaveMark(merId, uid, mark) {
return request.post(`service/mark/${merId}/${uid}`, {
mark
})
}
/**
* 获取会员卡类型
* @param object data
*
*/
export function memberCard() {
return request.get(`svip/pay_lst`)
}
/**
* 开通付费会员--支付
* @param object data
*
*/
export function memberCardCreate(id, data) {
return request.post(`svip/pay/${id}`, data)
}
/**
* 付费会员权益
* @param object data
*
*/
export function memberEquity() {
return request.get(`svip/user_info`, {}, {
noAuth: true
})
}
/**
* 付费会员优惠券
* @param object data
*
*/
export function memberCouponLst() {
return request.get(`svip/coupon_lst`, {}, {
noAuth: true
})
}
/**
* 付费会员优惠券--领取
* @param object data
*
*/
export function receiveMemberCoupon(id) {
return request.post(`svip/coupon_receive/${id}`)
}
/**
* 付费会员--会员商品
* @param object data
*
*/
export function groomList(data) {
return request.get(`svip/product_lst`, data, {
noAuth: true
})
}
/**
* 客服聊天--撤回消息
* @param object data
*
*/
export function chatReverstApi(id) {
return request.post(`service/recall/${id}`)
}

289
components/UploadDemo.vue Normal file
View File

@ -0,0 +1,289 @@
<template>
<view>
<view class="upload-wrap">
<view class="btn-click mgb-16 upload-btn" @click="handleUploadClick" v-show="!disabled">
<image :src="icons.upload" mode="aspectFill" class="upload-icon" />
<text class="upload-text">上传{{ title[type] }}</text>
</view>
<view class="mgb-16 file-wrap" v-for="(item, index) in fileList" :key="index">
<view class="btn-click file-line" @click="handlePreview(item)">
<!-- <view class="btn-click file-line" @click="handleUploadFile(item)"> -->
<view class="file-info">
<image :src="icons[item.fileType || 'file']" mode="aspectFill" class="file-icon" />
<text class="file-name">{{ item.name || title[type] }}</text>
</view>
<image :src="icons.close" mode="aspectFill" class="file-icon" v-if="!disabled"
@click.stop="handleDeleteFile(index)" />
</view>
</view>
<view class="mgb-16 file-wrap" v-if="fileList.length === 0 && disabled">
<view class="file-line">
<text class="file-empty">暂无数据</text>
</view>
</view>
</view>
<xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload>
</view>
</template>
<script>
export default {
name: 'UploadDemo',
components: {},
props: {
type: {
default: 'image', // image, video, file
type: String,
},
list: {
default: () => ([]),
type: Array,
},
disabled: {
default: false,
type: Boolean,
},
},
data() {
return {
// uploadOptions uni.uploadFileFunction
uploadOptions: {
// url: 'http://192.168.31.185:3000/api/upload', //
},
fileList: [],
title: {
image: '图片',
video: '视频',
file: '文件',
},
icons: {
upload: '/static/icon_upload.png',
close: '/static/icon_close.png',
image: '/static/icon_image.png',
video: '/static/icon_video.png',
file: '/static/icon_file.png',
},
};
},
watch: {
list: {
handler(val) {
this.fileList = val || [];
},
immediate: true,
deep: true,
},
},
methods: {
handleUploadClick() {
// 使
// AppH5 { extension: ['.doc', '.docx'] } { extension: '.doc, .docx' }
this.$refs.XeUpload.upload(this.type);
//
// chooseMedia使chooseMedia
// // uni.chooseImage
// this.$refs.XeUpload.upload(type, {
// count: 6,
// sizeType: ['original', 'compressed'],
// sourceType: ['album'],
// });
// // uni.chooseVideo
// this.$refs.XeUpload.upload(type, {
// sourceType: ['camera', 'album'],
// });
// // uni.chooseMedia (2.10.0+;;)
// this.$refs.XeUpload.upload(type, {
// count: 9,
// sourceType: ['album', 'camera'],
// });
},
handleUploadCallback(e) {
console.log('UploadCallback', e);
if (['choose', 'success'].includes(e.type)) {
// response
const tmpFiles = (e.data || []).map(({ response, tempFilePath, name, fileType }) => {
//
// {
// "result": {
// "fileName": "fileName",
// "filePath": `http://192.168.1.121:3000/static/xxxxx.png`,
// },
// "success": true,
// }
const res = response?.result || {};
const tmpUrl = res.filePath ?? tempFilePath;
const tmpName = res.fileName ?? name;
return {
...res,
url: tmpUrl,
name: tmpName,
fileType,
};
});
this.fileList.push(...tmpFiles);
}
},
//
handleUploadFile({ url }) {
console.log('UploadFile', url);
uni.uploadFile({
url: 'http://192.168.31.185:3000/api/upload',
filePath: url,
name: 'file',
success: (res) => {
console.log('handleUpload success', res);
const tmpData = JSON.parse(res.data);
uni.showToast({ title: tmpData.success ? '上传成功' : '上传失败', icon: 'none' });
},
fail: (err) => {
console.log('handleUpload fail', err);
uni.showToast({ title: '出错啦', icon: 'none' });
},
});
},
//
handlePreview({ url }) {
console.log('PreviewFile', url);
const fileType = this.getFileType(url);
if (fileType === 'image') {
return uni.previewImage({
current: url,
urls: [url],
});
}
// #ifndef H5
if (fileType === 'office') {
return uni.openDocument({
filePath: url,
fail: (err) => {
console.log(err);
uni.showToast({ icon: 'none', title: '文件预览失败' });
},
});
}
// #endif
uni.showModal({
title: '提示',
content: url,
showCancel: false,
});
},
handleDeleteFile(index) {
this.fileList.splice(index, 1);
},
/**
* 获取文件类型
* @param {String} fileName 文件链接
* @returns {String} fileType => '', image, video, audio, office, unknown
*/
getFileType(fileName = '') {
const flieArr = fileName.split('.');
let suffix = flieArr[flieArr.length - 1];
if (!suffix) return '';
suffix = suffix.toLocaleLowerCase();
const image = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp'];
if (image.includes(suffix)) return 'image';
const video = ['mp4', 'm4v'];
if (video.includes(suffix)) return 'video';
const audio = ['mp3', 'm4a', 'wav', 'aac'];
if (audio.includes(suffix)) return 'audio';
const office = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'plain'];
if (office.includes(suffix)) return 'office';
return 'unknown';
},
},
};
</script>
<style lang="scss" scoped>
view {
box-sizing: border-box;
}
.btn-click {
transition: all 0.3s;
opacity: 1;
}
.btn-click:active {
opacity: 0.5;
}
.mgb-16 {
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
.upload-wrap {
width: 100%;
border-radius: 16rpx;
background: white;
padding: 32rpx;
.upload-btn {
width: 100%;
height: 176rpx;
border: 2rpx dashed #AAAAAA;
background: #FAFAFA;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.upload-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 8rpx;
}
.upload-text {
font-size: 26rpx;
color: #9E9E9E;
line-height: 40rpx;
}
}
.file-wrap {
.file-line {
width: 100%;
background: #F5F5F5;
border-radius: 8rpx;
padding: 16rpx;
font-size: 26rpx;
color: #1A1A1A;
line-height: 40rpx;
display: flex;
align-items: center;
justify-content: space-between;
.file-info {
width: 90%;
display: flex;
align-items: center;
.file-name {
max-width: 80%;
padding-left: 16rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.file-icon {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.file-empty {
color: #999999;
}
}
}
}
</style>

View File

@ -0,0 +1,815 @@
<!--
parser 主模块组件
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
插件市场https://ext.dcloud.net.cn/plugin?id=805
authorJinYufeng
update2020/04/14
-->
<template>
<view>
<slot v-if="!nodes.length" />
<!--#ifdef APP-PLUS-NVUE-->
<web-view id="top" ref="web" :src="src" :style="'margin-top:-2px;height:'+height+'px'" @onPostMessage="_message" />
<!--#endif-->
<!--#ifndef APP-PLUS-NVUE-->
<view id="top" :style="showAm+(selectable?';user-select:text;-webkit-user-select:text':'')" :animation="scaleAm" @tap="_tap"
@touchstart="_touchstart" @touchmove="_touchmove">
<!--#ifdef H5-->
<div :id="'rtf'+uid"></div>
<!--#endif-->
<!--#ifndef H5-->
<trees :nodes="nodes" :lazy-load="lazyLoad" :loadVideo="loadVideo" />
<image v-for="(item, index) in imgs" v-bind:key="index" :id="index" :src="item" hidden @load="_load" />
<!--#endif-->
<image v-for="(item, index) in imgs" v-bind:key="index" :id="index" :src="item" hidden @load="_load" />
</view>
<!--#endif-->
</view>
</template>
<script>
// #ifndef H5 || APP-PLUS-NVUE
import trees from './libs/trees';
var cache = {},
// #ifdef MP-WEIXIN || MP-TOUTIAO
fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null,
// #endif
Parser = require('./libs/MpHtmlParser.js');
var document; // document https://jin-yufeng.github.io/Parser/#/instructions?id=document
// cache key
function hash(str) {
for (var i = str.length, val = 5381; i--;)
val += (val << 5) + str.charCodeAt(i);
return val;
}
// #endif
// #ifdef H5 || APP-PLUS-NVUE
var rpx = uni.getSystemInfoSync().screenWidth / 750,
cfg = require('./libs/config.js');
// #endif
// #ifdef APP-PLUS-NVUE
var dom = weex.requireModule('dom');
// #endif
export default {
name: 'parser',
data() {
return {
// #ifdef APP-PLUS
loadVideo: false,
// #endif
// #ifdef H5
uid: this._uid,
// #endif
// #ifdef APP-PLUS-NVUE
src: '',
height: 1,
// #endif
// #ifndef APP-PLUS-NVUE
scaleAm: '',
showAm: '',
imgs: [],
// #endif
nodes: []
}
},
// #ifndef H5 || APP-PLUS-NVUE
components: {
trees
},
// #endif
props: {
'html': null,
// #ifndef MP-ALIPAY
'autopause': {
type: Boolean,
default: true
},
// #endif
'autosetTitle': {
type: Boolean,
default: true
},
// #ifndef H5 || APP-PLUS-NVUE
'compress': Number,
'useCache': Boolean,
'xml': Boolean,
// #endif
'domain': String,
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
'gestureZoom': Boolean,
// #endif
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
'lazyLoad': Boolean,
// #endif
'selectable': Boolean,
'tagStyle': Object,
'showWithAnimation': Boolean,
'useAnchor': Boolean
},
watch: {
html(html) {
this.setContent(html);
}
},
mounted() {
//
this.imgList = [];
this.imgList.each = function(f) {
for (var i = 0, len = this.length; i < len; i++)
this.setItem(i, f(this[i], i, this));
}
this.imgList.setItem = function(i, src) {
if (i == void 0 || !src) return;
// #ifndef MP-ALIPAY || APP-PLUS
//
if (src.indexOf('http') == 0 && this.includes(src)) {
var newSrc = '';
for (var j = 0, c; c = src[j]; j++) {
if (c == '/' && src[j - 1] != '/' && src[j + 1] != '/') break;
newSrc += Math.random() > 0.5 ? c.toUpperCase() : c;
}
newSrc += src.substr(j);
return this[i] = newSrc;
}
// #endif
this[i] = src;
// data src
if (src.includes('data:image')) {
var filePath, info = src.match(/data:image\/(\S+?);(\S+?),(.+)/);
if (!info) return;
// #ifdef MP-WEIXIN || MP-TOUTIAO
filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`;
fs && fs.writeFile({
filePath,
data: info[3],
encoding: info[2],
success: () => this[i] = filePath
})
// #endif
// #ifdef APP-PLUS
filePath = `_doc/parser_tmp/${Date.now()}.${info[1]}`;
var bitmap = new plus.nativeObj.Bitmap();
bitmap.loadBase64Data(src, () => {
bitmap.save(filePath, {}, () => {
bitmap.clear()
this[i] = filePath;
})
})
// #endif
}
}
if (this.html) this.setContent(this.html);
},
beforeDestroy() {
// #ifdef H5
if (this._observer) this._observer.disconnect();
// #endif
this.imgList.each(src => {
// #ifdef APP-PLUS
if (src && src.includes('_doc')) {
plus.io.resolveLocalFileSystemURL(src, entry => {
entry.remove();
});
}
// #endif
// #ifdef MP-WEIXIN || MP-TOUTIAO
if (src && src.includes(uni.env.USER_DATA_PATH))
fs && fs.unlink({
filePath: src
})
// #endif
})
clearInterval(this._timer);
},
methods: {
// #ifdef H5 || APP-PLUS-NVUE
_Dom2Str(nodes) {
var str = '';
for (var node of nodes) {
if (node.type == 'text')
str += node.text;
else {
str += ('<' + node.name);
for (var attr in node.attrs || {})
str += (' ' + attr + '="' + node.attrs[attr] + '"');
if (!node.children || !node.children.length) str += '>';
else str += ('>' + this._Dom2Str(node.children) + '</' + node.name + '>');
}
}
return str;
},
_handleHtml(html, append) {
if (typeof html != 'string') html = this._Dom2Str(html.nodes || html);
// rpx
if (html.includes('rpx'))
html = html.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * rpx + 'px');
if (!append) {
// tag-style userAgentStyles
var style = '<style>@keyframes show{0%{opacity:0}100%{opacity:1}}';
for (var item in cfg.userAgentStyles)
style += `${item}{${cfg.userAgentStyles[item]}}`;
for (item in this.tagStyle)
style += `${item}{${this.tagStyle[item]}}`;
style += '</style>';
html = style + html;
}
return html;
},
// #endif
setContent(html, append) {
// #ifdef APP-PLUS-NVUE
if (!html) {
this.src = '';
this.height = 1;
return;
}
if (append) return;
plus.io.resolveLocalFileSystemURL('_doc', entry => {
entry.getDirectory('parser_tmp', {
create: true
}, entry => {
var fileName = Date.now() + '.html';
entry.getFile(fileName, {
create: true
}, entry => {
entry.createWriter(writer => {
writer.onwriteend = () => {
this.nodes = [1];
this.src = '_doc/parser_tmp/' + fileName;
this.$nextTick(function() {
entry.remove();
})
}
html =
'<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1' +
(this.selectable ? '' : ',user-scalable=no') +
'"><script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></' +
'script><base href="' + this.domain + '">' + this._handleHtml(html) +
'<script>"use strict";function post(t){uni.postMessage({data:t})}' +
(this.showWithAnimation ? 'document.body.style.animation="show .5s",' : '') +
'document.addEventListener("UniAppJSBridgeReady",function(){post({action:"load",text:document.body.innerText});var t=document.getElementsByTagName("title");t.length&&post({action:"getTitle",title:t[0].innerText});for(var e,o=document.getElementsByTagName("img"),n=[],i=0,r=0;e=o[i];i++)e.onerror=function(){post({action:"error",source:"img",target:this})},e.hasAttribute("ignore")||"A"==e.parentElement.nodeName||(e.i=r++,n.push(e.src),e.onclick=function(){post({action:"preview",img:{i:this.i,src:this.src}})});post({action:"getImgList",imgList:n});for(var a,s=document.getElementsByTagName("a"),c=0;a=s[c];c++)a.onclick=function(){var t,e=this.getAttribute("href");if("#"==e[0]){var r=document.getElementById(e.substr(1));r&&(t=r.offsetTop)}return post({action:"linkpress",href:e,offset:t}),!1};;for(var u,m=document.getElementsByTagName("video"),d=0;u=m[d];d++)u.style.maxWidth="100%;",u.onerror=function(){post({action:"error",source:"video",target:this})}' +
(this.autopause ? ',u.onplay=function(){for(var t,e=0;t=m[e];e++)t!=this&&t.pause()}' : '') +
';for(var g,l=document.getElementsByTagName("audio"),p=0;g=l[p];p++)g.onerror=function(){post({action:"error",source:"audio",target:this})};window.onload=function(){post({action:"ready",height:document.body.scrollHeight})}});</' +
'script>';
writer.write(html);
});
})
})
})
// #endif
// #ifdef H5
if (!html) {
if (this.rtf && !append) this.rtf.parentNode.removeChild(this.rtf);
return;
}
var div = document.createElement('div');
if (!append) {
if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
this.rtf = div;
} else {
if (!this.rtf) this.rtf = div;
else this.rtf.appendChild(div);
}
div.innerHTML = this._handleHtml(html, append);
for (var styles = this.rtf.getElementsByTagName('style'), i = 0, style; style = styles[i++];) {
style.innerHTML = style.innerHTML.replace(/body/g, '#rtf' + this._uid);
style.setAttribute('scoped', 'true');
}
//
if (!this._observer && this.lazyLoad && IntersectionObserver) {
this._observer = new IntersectionObserver(changes => {
for (let item, i = 0; item = changes[i++];) {
if (item.isIntersecting) {
item.target.src = item.target.getAttribute('data-src');
item.target.removeAttribute('data-src');
this._observer.unobserve(item.target);
}
}
}, {
rootMargin: '900px 0px 900px 0px'
})
}
var _ts = this;
//
var title = this.rtf.getElementsByTagName('title');
if (title.length && this.autosetTitle)
uni.setNavigationBarTitle({
title: title[0].innerText
})
//
this.imgList.length = 0;
var imgs = this.rtf.getElementsByTagName('img');
for (let i = 0, j = 0, img; img = imgs[i]; i++) {
img.style.maxWidth = '100%';
var src = img.getAttribute('src');
if (this.domain && src) {
if (src[0] == '/') {
if (src[1] == '/')
img.src = (this.domain.includes('://') ? this.domain.split('://')[0] : '') + ':' + src;
else img.src = this.domain + src;
} else if (!src.includes('://')) img.src = this.domain + '/' + src;
}
if (!img.hasAttribute('ignore') && img.parentElement.nodeName != 'A') {
img.i = j++;
_ts.imgList.push(img.src || img.getAttribute('data-src'));
img.onclick = function() {
var preview = true;
this.ignore = () => preview = false;
_ts.$emit('imgtap', this);
if (preview) {
uni.previewImage({
current: this.i,
urls: _ts.imgList
});
}
}
}
img.onerror = function() {
_ts.$emit('error', {
source: 'img',
target: this
});
}
if (_ts.lazyLoad && this._observer && img.src && img.i != 0) {
img.setAttribute('data-src', img.src);
img.removeAttribute('src');
this._observer.observe(img);
}
}
//
var links = this.rtf.getElementsByTagName('a');
for (var link of links) {
link.onclick = function() {
var jump = true,
href = this.getAttribute('href');
_ts.$emit('linkpress', {
href,
ignore: () => jump = false
});
if (jump && href) {
if (href[0] == '#') {
if (_ts.useAnchor) {
_ts.navigateTo({
id: href.substr(1)
})
}
} else if (href.indexOf('http') == 0 || href.indexOf('//') == 0)
return true;
else {
uni.navigateTo({
url: href
})
}
}
return false;
}
}
//
var videos = this.rtf.getElementsByTagName('video');
_ts.videoContexts = videos;
for (let video, i = 0; video = videos[i++];) {
video.style.maxWidth = '100%';
video.onerror = function() {
_ts.$emit('error', {
source: 'video',
target: this
});
}
video.onplay = function() {
if (_ts.autopause)
for (let item, i = 0; item = _ts.videoContexts[i++];)
if (item != this) item.pause();
}
}
//
var audios = this.rtf.getElementsByTagName('audios');
for (var audio of audios)
audio.onerror = function() {
_ts.$emit('error', {
source: 'audio',
target: this
});
}
this.document = this.rtf;
if (!append) document.getElementById('rtf' + this._uid).appendChild(this.rtf);
this.$nextTick(() => {
this.nodes = [1];
this.$emit('load');
})
setTimeout(() => this.showAm = '', 500);
// #endif
// #ifndef H5 || APP-PLUS-NVUE
var nodes;
if (!html)
return this.nodes = [];
else if (typeof html == 'string') {
let parser = new Parser(html, this);
//
if (this.useCache) {
var hashVal = hash(html);
if (cache[hashVal])
nodes = cache[hashVal];
else {
nodes = parser.parse();
cache[hashVal] = nodes;
}
} else nodes = parser.parse();
this.$emit('parse', nodes);
} else if (Object.prototype.toString.call(html) == '[object Array]') {
// array
if (html.length && html[0].PoweredBy != 'Parser') {
let parser = new Parser(html, this);
(function f(ns) {
for (var i = 0, n; n = ns[i]; i++) {
if (n.type == 'text') continue;
n.attrs = n.attrs || {};
for (var item in n.attrs)
if (typeof n.attrs[item] != 'string') n.attrs[item] = n.attrs[item].toString();
parser.matchAttr(n, parser);
if (n.children && n.children.length) {
parser.STACK.push(n);
f(n.children);
parser.popNode(parser.STACK.pop());
} else n.children = void 0;
}
})(html);
}
nodes = html;
} else if (typeof html == 'object' && html.nodes) {
nodes = html.nodes;
console.warn('错误的 html 类型object 类型已废弃');
} else
return console.warn('错误的 html 类型:' + typeof html);
// #ifdef APP-PLUS
this.loadVideo = false;
// #endif
if (document) this.document = new document(this.nodes, 'nodes', this);
if (append) this.nodes = this.nodes.concat(nodes);
else this.nodes = nodes;
if (nodes.length && nodes[0].title && this.autosetTitle)
uni.setNavigationBarTitle({
title: nodes[0].title
})
this.$nextTick(() => {
this.imgList.length = 0;
this.videoContexts = [];
// #ifdef MP-TOUTIAO
setTimeout(() => {
// #endif
var f = (cs) => {
for (let i = 0, c; c = cs[i++];) {
if (c.$options.name == 'trees') {
for (var j = c.nodes.length, item; item = c.nodes[--j];) {
if (item.c) continue;
if (item.name == 'img') {
this.imgList.setItem(item.attrs.i, item.attrs.src);
// #ifndef MP-ALIPAY
if (!c.observer && !c.imgLoad && item.attrs.i != '0') {
if (this.lazyLoad && uni.createIntersectionObserver) {
c.observer = uni.createIntersectionObserver(c);
c.observer.relativeToViewport({
top: 900,
bottom: 900
}).observe('._img', () => {
c.imgLoad = true;
c.observer.disconnect();
})
} else
c.imgLoad = true;
}
// #endif
}
// #ifndef MP-ALIPAY
else if (item.name == 'video') {
var ctx = uni.createVideoContext(item.attrs.id, c);
ctx.id = item.attrs.id;
this.videoContexts.push(ctx);
}
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (item.attrs && item.attrs.id) {
this.anchors = this.anchors || [];
this.anchors.push({
id: item.attrs.id,
node: c
})
}
// #endif
}
}
if (c.$children.length)
f(c.$children)
}
}
f(this.$children);
// #ifdef MP-TOUTIAO
}, 200)
this.$emit('load');
// #endif
// #ifdef APP-PLUS
setTimeout(() => {
this.loadVideo = true;
}, 3000);
// #endif
})
// #endif
// #ifndef APP-PLUS-NVUE
var height;
clearInterval(this._timer);
this._timer = setInterval(() => {
// #ifdef H5
var res = [this.rtf.getBoundingClientRect()];
// #endif
// #ifndef H5
// #ifdef APP-PLUS
uni.createSelectorQuery().in(this)
// #endif
// #ifndef APP-PLUS
this.createSelectorQuery()
// #endif
.select('#top').boundingClientRect().exec(res => {
// #endif
this.width = res[0].width;
if (res[0].height == height) {
this.$emit('ready', res[0])
clearInterval(this._timer);
}
height = res[0].height;
// #ifndef H5
});
// #endif
}, 350)
if (this.showWithAnimation && !append) this.showAm = 'animation:show .5s';
// #endif
},
getText(ns = this.nodes) {
// #ifdef APP-PLUS-NVUE
return this._text;
// #endif
// #ifdef H5
return this.rtf.innerText;
// #endif
// #ifndef H5 || APP-PLUS-NVUE
var txt = '';
for (var i = 0, n; n = ns[i++];) {
if (n.type == 'text') txt += n.text.replace(/&nbsp;/g, '\u00A0').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
.replace(/&amp;/g, '&');
else if (n.type == 'br') txt += '\n';
else {
//
var block = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] >
'0' && n.name[1] < '7');
if (block && txt && txt[txt.length - 1] != '\n') txt += '\n';
if (n.children) txt += this.getText(n.children);
if (block && txt[txt.length - 1] != '\n') txt += '\n';
else if (n.name == 'td' || n.name == 'th') txt += '\t';
}
}
return txt;
// #endif
},
navigateTo(obj) {
if (!this.useAnchor)
return obj.fail && obj.fail({
errMsg: 'Anchor is disabled'
})
// #ifdef APP-PLUS-NVUE
if (!obj.id)
dom.scrollToElement(this.$refs.web);
else
this.$refs.web.evalJs('var pos=document.getElementById("' + obj.id +
'");if(pos)post({action:"linkpress",href:"#",offset:pos.offsetTop})');
return obj.success && obj.success({
errMsg: 'pageScrollTo:ok'
});
// #endif
// #ifdef H5
if (!obj.id) {
window.scrollTo(0, this.rtf.offsetTop);
return obj.success && obj.success({
errMsg: 'pageScrollTo:ok'
});
}
var target = document.getElementById(obj.id);
if (!target) return obj.fail && obj.fail({
errMsg: 'Label not found'
});
obj.scrollTop = this.rtf.offsetTop + target.offsetTop;
uni.pageScrollTo(obj);
// #endif
// #ifndef H5
var Scroll = (selector, component) => {
uni.createSelectorQuery().in(component ? component : this).select(selector).boundingClientRect().selectViewport()
.scrollOffset()
.exec(res => {
if (!res || !res[0])
return obj.fail && obj.fail({
errMsg: 'Label not found'
});
obj.scrollTop = res[1].scrollTop + res[0].top;
uni.pageScrollTo(obj);
})
}
if (!obj.id) Scroll('#top');
else {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
Scroll('#top >>> #' + obj.id + ', #top >>> .' + obj.id);
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || APP-PLUS
for (var anchor of this.anchors)
if (anchor.id == obj.id)
Scroll('#' + obj.id + ', .' + obj.id, anchor.node);
// #endif
}
// #endif
},
getVideoContext(id) {
// #ifndef APP-PLUS-NVUE
if (!id) return this.videoContexts;
else
for (var i = this.videoContexts.length; i--;)
if (this.videoContexts[i].id == id) return this.videoContexts[i];
// #endif
},
//
preLoad(html, num) {
// #ifdef H5 || APP-PLUS-NVUE
if (html.constructor == Array)
html = this._Dom2Str(html);
var script = "var contain=document.createElement('div');contain.innerHTML='" + html.replace(/'/g, "\\'") +
"';for(var imgs=contain.querySelectorAll('img'),i=imgs.length-1;i>=" + num +
";i--)imgs[i].removeAttribute('src');";
// #endif
// #ifdef APP-PLUS-NVUE
this.$refs.web.evalJs(script);
// #endif
// #ifdef H5
eval(script);
// #endif
// #ifndef H5 || APP-PLUS-NVUE
if (typeof html == 'string') {
var id = hash(html);
html = new Parser(html, this).parse();
cache[id] = html;
}
var wait = [];
(function f(ns) {
for (var i = 0, n; n = ns[i++];) {
if (n.name == 'img' && n.attrs.src && !wait.includes(n.attrs.src))
wait.push(n.attrs.src);
f(n.children || []);
}
})(html);
if (num) wait = wait.slice(0, num);
this._wait = (this._wait || []).concat(wait);
if (!this.imgs) this.imgs = this._wait.splice(0, 15);
else if (this.imgs.length < 15)
this.imgs = this.imgs.concat(this._wait.splice(0, 15 - this.imgs.length));
// #endif
},
// #ifdef APP-PLUS-NVUE
_message(e) {
// web-view
var data = e.detail.data[0];
if (data.action == 'load') {
this.$emit('load');
this._text = data.text;
} else if (data.action == 'getTitle') {
if (this.autosetTitle)
uni.setNavigationBarTitle({
title: data.title
})
} else if (data.action == 'getImgList') {
this.imgList.length = 0;
for (var i = data.imgList.length; i--;)
this.imgList.setItem(i, data.imgList[i]);
} else if (data.action == 'preview') {
var preview = true;
data.img.ignore = () => preview = false;
this.$emit('imgtap', data.img);
if (preview)
uni.previewImage({
current: data.img.i,
urls: this.imgList
})
} else if (data.action == 'linkpress') {
var jump = true,
href = data.href;
this.$emit('linkpress', {
href,
ignore: () => jump = false
})
if (jump && href) {
if (href[0] == '#') {
if (this.useAnchor)
dom.scrollToElement(this.$refs.web, {
offset: data.offset
})
} else if (href.includes('://'))
plus.runtime.openWeb(href);
else
uni.navigateTo({
url: href
})
}
} else if (data.action == 'error')
this.$emit('error', {
source: data.source,
target: data.target
})
else if (data.action == 'ready') {
this.height = data.height;
this.$nextTick(() => {
uni.createSelectorQuery().in(this).select('#top').boundingClientRect().exec(res => {
this.rect = res[0];
this.$emit('ready', res[0]);
})
})
}
},
// #endif
// #ifndef APP-PLUS-NVUE
// #ifndef H5
_load(e) {
if (this._wait.length)
this.$set(this.imgs, e.target.id, this._wait.shift());
},
// #endif
_tap(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (this.gestureZoom && e.timeStamp - this._lastT < 300) {
var initY = e.touches[0].pageY - e.currentTarget.offsetTop;
if (this._zoom) {
this._scaleAm.translateX(0).scale(1).step();
uni.pageScrollTo({
scrollTop: (initY + this._initY) / 2 - e.touches[0].clientY,
duration: 400
})
} else {
var initX = e.touches[0].pageX - e.currentTarget.offsetLeft;
this._initY = initY;
this._scaleAm = uni.createAnimation({
transformOrigin: `${initX}px ${this._initY}px 0`,
timingFunction: 'ease-in-out'
});
// #ifdef MP-TOUTIAO
this._scaleAm.opacity(1);
// #endif
this._scaleAm.scale(2).step();
this._tMax = initX / 2;
this._tMin = (initX - this.width) / 2;
this._tX = 0;
}
this._zoom = !this._zoom;
this.scaleAm = this._scaleAm.export();
}
this._lastT = e.timeStamp;
// #endif
},
_touchstart(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
if (e.touches.length == 1)
this._initX = this._lastX = e.touches[0].pageX;
// #endif
},
_touchmove(e) {
// #ifndef MP-BAIDU || MP-ALIPAY || APP-PLUS
var diff = e.touches[0].pageX - this._lastX;
if (this._zoom && e.touches.length == 1 && Math.abs(diff) > 20) {
this._lastX = e.touches[0].pageX;
if ((this._tX <= this._tMin && diff < 0) || (this._tX >= this._tMax && diff > 0))
return;
this._tX += (diff * Math.abs(this._lastX - this._initX) * 0.05);
if (this._tX < this._tMin) this._tX = this._tMin;
if (this._tX > this._tMax) this._tX = this._tMax;
this._scaleAm.translateX(this._tX).step();
this.scaleAm = this._scaleAm.export();
}
// #endif
}
// #endif
}
}
</script>
<style>
@keyframes show {
0% {
opacity: 0
}
100% {
opacity: 1;
}
}
/* #ifdef MP-WEIXIN */
:host {
display: block;
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
/* #endif */
</style>

View File

@ -0,0 +1,111 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/*
解析和匹配 Css 的选择器
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
authorJinYufeng
update2020/03/15
*/
var cfg = require('./config.js');
class CssHandler {
constructor(tagStyle) {
var styles = Object.assign({}, cfg.userAgentStyles);
for (var item in tagStyle)
styles[item] = (styles[item] ? styles[item] + ';' : '') + tagStyle[item];
this.styles = styles;
}
getStyle = data => this.styles = new CssParser(data, this.styles).parse();
match(name, attrs) {
var tmp, matched = (tmp = this.styles[name]) ? tmp + ';' : '';
if (attrs.class) {
var items = attrs.class.split(' ');
for (var i = 0, item; item = items[i]; i++)
if (tmp = this.styles['.' + item])
matched += tmp + ';';
}
if (tmp = this.styles['#' + attrs.id])
matched += tmp + ';';
return matched;
}
}
module.exports = CssHandler;
class CssParser {
constructor(data, init) {
this.data = data;
this.floor = 0;
this.i = 0;
this.list = [];
this.res = init;
this.state = this.Space;
}
parse() {
for (var c; c = this.data[this.i]; this.i++)
this.state(c);
return this.res;
}
section = () => this.data.substring(this.start, this.i);
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
// 状态机
Space(c) {
if (c == '.' || c == '#' || this.isLetter(c)) {
this.start = this.i;
this.state = this.Name;
} else if (c == '/' && this.data[this.i + 1] == '*')
this.Comment();
else if (!cfg.blankChar[c] && c != ';')
this.state = this.Ignore;
}
Comment() {
this.i = this.data.indexOf('*/', this.i) + 1;
if (!this.i) this.i = this.data.length;
this.state = this.Space;
}
Ignore(c) {
if (c == '{') this.floor++;
else if (c == '}' && !--this.floor) this.state = this.Space;
}
Name(c) {
if (cfg.blankChar[c]) {
this.list.push(this.section());
this.state = this.NameSpace;
} else if (c == '{') {
this.list.push(this.section());
this.Content();
} else if (c == ',') {
this.list.push(this.section());
this.Comma();
} else if (!this.isLetter(c) && (c < '0' || c > '9') && c != '-' && c != '_')
this.state = this.Ignore;
}
NameSpace(c) {
if (c == '{') this.Content();
else if (c == ',') this.Comma();
else if (!cfg.blankChar[c]) this.state = this.Ignore;
}
Comma() {
while (cfg.blankChar[this.data[++this.i]]);
if (this.data[this.i] == '{') this.Content();
else {
this.start = this.i--;
this.state = this.Name;
}
}
Content() {
this.start = ++this.i;
if ((this.i = this.data.indexOf('}', this.i)) == -1) this.i = this.data.length;
var content = this.section();
for (var i = 0, item; item = this.list[i++];)
if (this.res[item]) this.res[item] += ';' + content;
else this.res[item] = content;
this.list = [];
this.state = this.Space;
}
}

View File

@ -0,0 +1,586 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/*
html 解析为适用于小程序 rich-text DOM 结构
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
authorJinYufeng
update2020/04/13
*/
var cfg = require('./config.js'),
blankChar = cfg.blankChar,
CssHandler = require('./CssHandler.js'),
{
screenWidth,
system
} = wx.getSystemInfoSync();
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
var entities = {
lt: '<',
gt: '>',
amp: '&',
quot: '"',
apos: "'",
nbsp: '\xA0',
ensp: '\u2002',
emsp: '\u2003',
ndash: '',
mdash: '—',
middot: '·',
lsquo: '',
rsquo: '',
ldquo: '“',
rdquo: '”',
bull: '•',
hellip: '…',
permil: '‰',
copy: '©',
reg: '®',
trade: '™',
times: '×',
divide: '÷',
cent: '¢',
pound: '£',
yen: '¥',
euro: '€',
sect: '§'
};
// #endif
var emoji; // emoji 补丁包 https://jin-yufeng.github.io/Parser/#/instructions?id=emoji
class MpHtmlParser {
constructor(data, options = {}) {
this.attrs = {};
this.compress = options.compress;
this.CssHandler = new CssHandler(options.tagStyle, screenWidth);
this.data = data;
this.domain = options.domain;
this.DOM = [];
this.i = this.start = this.audioNum = this.imgNum = this.videoNum = 0;
this.protocol = this.domain && this.domain.includes('://') ? this.domain.split('://')[0] : '';
this.state = this.Text;
this.STACK = [];
this.useAnchor = options.useAnchor;
this.xml = options.xml;
}
parse() {
if (emoji) this.data = emoji.parseEmoji(this.data);
for (var c; c = this.data[this.i]; this.i++)
this.state(c);
if (this.state == this.Text) this.setText();
while (this.STACK.length) this.popNode(this.STACK.pop());
// #ifdef MP-BAIDU || MP-TOUTIAO
// 将顶层标签的一些样式提取出来给 rich-text
(function f(ns) {
for (var i = ns.length, n; n = ns[--i];) {
if (n.type == 'text') continue;
if (!n.c) {
var style = n.attrs.style;
if (style) {
var j, k, res;
if ((j = style.indexOf('display')) != -1)
res = style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
if ((j = style.indexOf('float')) != -1)
res += ';' + style.substring(j, (k = style.indexOf(';', j)) == -1 ? style.length : k);
n.attrs.contain = res;
}
} else f(n.children);
}
})(this.DOM);
// #endif
if (this.DOM.length) {
this.DOM[0].PoweredBy = 'Parser';
if (this.title) this.DOM[0].title = this.title;
}
return this.DOM;
}
// 设置属性
setAttr() {
var name = this.getName(this.attrName);
if (cfg.trustAttrs[name]) {
if (!this.attrVal) {
if (cfg.boolAttrs[name]) this.attrs[name] = 'T';
} else if (name == 'src') this.attrs[name] = this.getUrl(this.attrVal.replace(/&amp;/g, '&'));
else this.attrs[name] = this.attrVal;
}
this.attrVal = '';
while (blankChar[this.data[this.i]]) this.i++;
if (this.isClose()) this.setNode();
else {
this.start = this.i;
this.state = this.AttrName;
}
}
// 设置文本节点
setText() {
var back, text = this.section();
if (!text) return;
text = (cfg.onText && cfg.onText(text, () => back = true)) || text;
if (back) {
this.data = this.data.substr(0, this.start) + text + this.data.substr(this.i);
let j = this.start + text.length;
for (this.i = this.start; this.i < j; this.i++) this.state(this.data[this.i]);
return;
}
if (!this.pre) {
// 合并空白符
var tmp = [];
for (let i = text.length, c; c = text[--i];)
if (!blankChar[c] || (!blankChar[tmp[0]] && (c = ' '))) tmp.unshift(c);
text = tmp.join('');
if (text == ' ') return;
}
// 处理实体
var siblings = this.siblings(),
i = -1,
j, en;
while (1) {
if ((i = text.indexOf('&', i + 1)) == -1) break;
if ((j = text.indexOf(';', i + 2)) == -1) break;
if (text[i + 1] == '#') {
en = parseInt((text[i + 2] == 'x' ? '0' : '') + text.substring(i + 2, j));
if (!isNaN(en)) text = text.substr(0, i) + String.fromCharCode(en) + text.substring(j + 1);
} else {
en = text.substring(i + 1, j);
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
if (en == 'nbsp') text = text.substr(0, i) + '\xA0' + text.substr(j + 1); // 解决 &nbsp; 失效
else if (en != 'lt' && en != 'gt' && en != 'amp' && en != 'ensp' && en != 'emsp' && en != 'quot' && en != 'apos') {
i && siblings.push({
type: 'text',
text: text.substr(0, i)
})
siblings.push({
type: 'text',
text: `&${en};`,
en: 1
})
text = text.substr(j + 1);
i = -1;
}
// #endif
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
if (entities[en]) text = text.substr(0, i) + entities[en] + text.substr(j + 1);
// #endif
}
}
text && siblings.push({
type: 'text',
text
})
}
// 设置元素节点
setNode() {
var node = {
name: this.tagName.toLowerCase(),
attrs: this.attrs
},
close = cfg.selfClosingTags[node.name] || (this.xml && this.data[this.i] == '/');
this.attrs = {};
if (!cfg.ignoreTags[node.name]) {
this.matchAttr(node);
if (!close) {
node.children = [];
if (node.name == 'pre' && cfg.highlight) {
this.remove(node);
this.pre = node.pre = true;
}
this.siblings().push(node);
this.STACK.push(node);
} else if (!cfg.filter || cfg.filter(node, this) != false)
this.siblings().push(node);
} else {
if (!close) this.remove(node);
else if (node.name == 'source') {
var parent = this.STACK[this.STACK.length - 1],
attrs = node.attrs;
if (parent && attrs.src)
if (parent.name == 'video' || parent.name == 'audio')
parent.attrs.source.push(attrs.src);
else {
var i, media = attrs.media;
if (parent.name == 'picture' && !parent.attrs.src && !(attrs.src.indexOf('.webp') && system.includes('iOS')) &&
(!media || (media.includes('px') &&
(((i = media.indexOf('min-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth > parseInt(
media.substr(i + 1))) ||
((i = media.indexOf('max-width')) != -1 && (i = media.indexOf(':', i + 8)) != -1 && screenWidth < parseInt(
media.substr(i + 1)))))))
parent.attrs.src = attrs.src;
}
} else if (node.name == 'base' && !this.domain) this.domain = node.attrs.href;
}
if (this.data[this.i] == '/') this.i++;
this.start = this.i + 1;
this.state = this.Text;
}
// 移除标签
remove(node) {
var name = node.name,
j = this.i;
while (1) {
if ((this.i = this.data.indexOf('</', this.i + 1)) == -1) {
if (name == 'pre' || name == 'svg') this.i = j;
else this.i = this.data.length;
return;
}
this.start = (this.i += 2);
while (!blankChar[this.data[this.i]] && !this.isClose()) this.i++;
if (this.getName(this.section()) == name) {
// 代码块高亮
if (name == 'pre') {
this.data = this.data.substr(0, j + 1) + cfg.highlight(this.data.substring(j + 1, this.i - 5), node.attrs) +
this.data.substr(this.i - 5);
return this.i = j;
} else if (name == 'style')
this.CssHandler.getStyle(this.data.substring(j + 1, this.i - 7));
else if (name == 'title')
this.title = this.data.substring(j + 1, this.i - 7);
if ((this.i = this.data.indexOf('>', this.i)) == -1) this.i = this.data.length;
// 处理 svg
if (name == 'svg') {
var src = this.data.substring(j, this.i + 1);
if (!node.attrs.xmlns) src = ' xmlns="http://www.w3.org/2000/svg"' + src;
var i = j;
while (this.data[j] != '<') j--;
src = this.data.substring(j, i) + src;
var parent = this.STACK[this.STACK.length - 1];
if (node.attrs.width == '100%' && parent && (parent.attrs.style || '').includes('inline'))
parent.attrs.style = 'width:300px;max-width:100%;' + parent.attrs.style;
this.siblings().push({
name: 'img',
attrs: {
src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
ignore: 'T'
}
})
}
return;
}
}
}
// 处理属性
matchAttr(node) {
var attrs = node.attrs,
style = this.CssHandler.match(node.name, attrs, node) + (attrs.style || ''),
styleObj = {};
if (attrs.id) {
if (this.compress & 1) attrs.id = void 0;
else if (this.useAnchor) this.bubble();
}
if ((this.compress & 2) && attrs.class) attrs.class = void 0;
switch (node.name) {
case 'img':
if (attrs['data-src']) {
attrs.src = attrs.src || attrs['data-src'];
attrs['data-src'] = void 0;
}
if (attrs.src && !attrs.ignore) {
if (this.bubble()) attrs.i = (this.imgNum++).toString();
else attrs.ignore = 'T';
}
break;
case 'a':
case 'ad':
// #ifdef APP-PLUS
case 'iframe':
case 'embed':
// #endif
this.bubble();
break;
case 'font':
if (attrs.color) {
styleObj['color'] = attrs.color;
attrs.color = void 0;
}
if (attrs.face) {
styleObj['font-family'] = attrs.face;
attrs.face = void 0;
}
if (attrs.size) {
var size = parseInt(attrs.size);
if (size < 1) size = 1;
else if (size > 7) size = 7;
var map = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
styleObj['font-size'] = map[size - 1];
attrs.size = void 0;
}
break;
case 'video':
case 'audio':
if (!attrs.id) attrs.id = node.name + (++this[`${node.name}Num`]);
else this[`${node.name}Num`]++;
if (node.name == 'video') {
if (attrs.width) {
style = `width:${parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')};${style}`;
attrs.width = void 0;
}
if (attrs.height) {
style = `height:${parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')};${style}`;
attrs.height = void 0;
}
if (this.videoNum > 3) node.lazyLoad = true;
}
attrs.source = [];
if (attrs.src) attrs.source.push(attrs.src);
if (!attrs.controls && !attrs.autoplay)
console.warn(`存在没有 controls 属性的 ${node.name} 标签,可能导致无法播放`, node);
this.bubble();
break;
case 'td':
case 'th':
if (attrs.colspan || attrs.rowspan)
for (var k = this.STACK.length, item; item = this.STACK[--k];)
if (item.name == 'table') {
item.c = void 0;
break;
}
}
if (attrs.align) {
styleObj['text-align'] = attrs.align;
attrs.align = void 0;
}
// 压缩 style
var styles = style.replace(/&quot;/g, '"').replace(/&amp;/g, '&').split(';');
style = '';
for (var i = 0, len = styles.length; i < len; i++) {
var info = styles[i].split(':');
if (info.length < 2) continue;
let key = info[0].trim().toLowerCase(),
value = info.slice(1).join(':').trim();
if (value.includes('-webkit') || value.includes('-moz') || value.includes('-ms') || value.includes('-o') || value
.includes(
'safe'))
style += `;${key}:${value}`;
else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import'))
styleObj[key] = value;
}
if (node.name == 'img' && parseInt(styleObj.width || attrs.width) > screenWidth)
styleObj.height = 'auto';
for (var key in styleObj) {
var value = styleObj[key];
if (key.includes('flex') || key == 'order' || key == 'self-align') node.c = 1;
// 填充链接
if (value.includes('url')) {
var j = value.indexOf('(');
if (j++ != -1) {
while (value[j] == '"' || value[j] == "'" || blankChar[value[j]]) j++;
value = value.substr(0, j) + this.getUrl(value.substr(j));
}
}
// 转换 rpx
else if (value.includes('rpx'))
value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * screenWidth / 750 + 'px');
else if (key == 'white-space' && value.includes('pre'))
this.pre = node.pre = true;
style += `;${key}:${value}`;
}
style = style.substr(1);
if (style) attrs.style = style;
}
// 节点出栈处理
popNode(node) {
// 空白符处理
if (node.pre) {
node.pre = this.pre = void 0;
for (let i = this.STACK.length; i--;)
if (this.STACK[i].pre)
this.pre = true;
}
if (node.name == 'head' || (cfg.filter && cfg.filter(node, this) == false))
return this.siblings().pop();
var attrs = node.attrs;
// 替换一些标签名
if (node.name == 'picture') {
node.name = 'img';
if (!attrs.src && (node.children[0] || '').name == 'img')
attrs.src = node.children[0].attrs.src;
if (attrs.src && !attrs.ignore)
attrs.i = (this.imgNum++).toString();
return node.children = void 0;
}
if (cfg.blockTags[node.name]) node.name = 'div';
else if (!cfg.trustTags[node.name]) node.name = 'span';
// 处理列表
if (node.c) {
if (node.name == 'ul') {
var floor = 1;
for (let i = this.STACK.length; i--;)
if (this.STACK[i].name == 'ul') floor++;
if (floor != 1)
for (let i = node.children.length; i--;)
node.children[i].floor = floor;
} else if (node.name == 'ol') {
for (let i = 0, num = 1, child; child = node.children[i++];)
if (child.name == 'li') {
child.type = 'ol';
child.num = ((num, type) => {
if (type == 'a') return String.fromCharCode(97 + (num - 1) % 26);
if (type == 'A') return String.fromCharCode(65 + (num - 1) % 26);
if (type == 'i' || type == 'I') {
num = (num - 1) % 99 + 1;
var one = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
ten = ['X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
res = (ten[Math.floor(num / 10) - 1] || '') + (one[num % 10 - 1] || '');
if (type == 'i') return res.toLowerCase();
return res;
}
return num;
})(num++, attrs.type) + '.';
}
}
}
// 处理表格的边框
if (node.name == 'table') {
var padding = attrs.cellpadding,
spacing = attrs.cellspacing,
border = attrs.border;
if (node.c) {
this.bubble();
if (!padding) padding = 2;
if (!spacing) spacing = 2;
}
if (border) attrs.style = `border:${border}px solid gray;${attrs.style || ''}`;
if (spacing) attrs.style = `border-spacing:${spacing}px;${attrs.style || ''}`;
if (border || padding)
(function f(ns) {
for (var i = 0, n; n = ns[i]; i++) {
if (n.name == 'th' || n.name == 'td') {
if (border) n.attrs.style = `border:${border}px solid gray;${n.attrs.style}`;
if (padding) n.attrs.style = `padding:${padding}px;${n.attrs.style}`;
} else f(n.children || []);
}
})(node.children)
}
this.CssHandler.pop && this.CssHandler.pop(node);
// 自动压缩
if (node.name == 'div' && !Object.keys(attrs).length) {
var siblings = this.siblings();
if (node.children.length == 1 && node.children[0].name == 'div')
siblings[siblings.length - 1] = node.children[0];
}
}
// 工具函数
bubble() {
for (var i = this.STACK.length, item; item = this.STACK[--i];) {
if (cfg.richOnlyTags[item.name]) {
if (item.name == 'table' && !Object.hasOwnProperty.call(item, 'c')) item.c = 1;
return false;
}
item.c = 1;
}
return true;
}
getName = val => this.xml ? val : val.toLowerCase();
getUrl(url) {
if (url[0] == '/') {
if (url[1] == '/') url = this.protocol + ':' + url;
else if (this.domain) url = this.domain + url;
} else if (this.domain && url.indexOf('data:') != 0 && !url.includes('://'))
url = this.domain + '/' + url;
return url;
}
isClose = () => this.data[this.i] == '>' || (this.data[this.i] == '/' && this.data[this.i + 1] == '>');
section = () => this.data.substring(this.start, this.i);
siblings = () => this.STACK.length ? this.STACK[this.STACK.length - 1].children : this.DOM;
// 状态机
Text(c) {
if (c == '<') {
var next = this.data[this.i + 1],
isLetter = c => (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
if (isLetter(next)) {
this.setText();
this.start = this.i + 1;
this.state = this.TagName;
} else if (next == '/') {
this.setText();
if (isLetter(this.data[++this.i + 1])) {
this.start = this.i + 1;
this.state = this.EndTag;
} else
this.Comment();
} else if (next == '!') {
this.setText();
this.Comment();
}
}
}
Comment() {
var key;
if (this.data.substring(this.i + 2, this.i + 4) == '--') key = '-->';
else if (this.data.substring(this.i + 2, this.i + 9) == '[CDATA[') key = ']]>';
else key = '>';
if ((this.i = this.data.indexOf(key, this.i + 2)) == -1) this.i = this.data.length;
else this.i += key.length - 1;
this.start = this.i + 1;
this.state = this.Text;
}
TagName(c) {
if (blankChar[c]) {
this.tagName = this.section();
while (blankChar[this.data[this.i]]) this.i++;
if (this.isClose()) this.setNode();
else {
this.start = this.i;
this.state = this.AttrName;
}
} else if (this.isClose()) {
this.tagName = this.section();
this.setNode();
}
}
AttrName(c) {
var blank = blankChar[c];
if (blank) {
this.attrName = this.section();
c = this.data[this.i];
}
if (c == '=') {
if (!blank) this.attrName = this.section();
while (blankChar[this.data[++this.i]]);
this.start = this.i--;
this.state = this.AttrValue;
} else if (blank) this.setAttr();
else if (this.isClose()) {
this.attrName = this.section();
this.setAttr();
}
}
AttrValue(c) {
if (c == '"' || c == "'") {
this.start++;
if ((this.i = this.data.indexOf(c, this.i + 1)) == -1) return this.i = this.data.length;
this.attrVal = this.section();
this.i++;
} else {
for (; !blankChar[this.data[this.i]] && !this.isClose(); this.i++);
this.attrVal = this.section();
}
this.setAttr();
}
EndTag(c) {
if (blankChar[c] || c == '>' || c == '/') {
var name = this.getName(this.section());
for (var i = this.STACK.length; i--;)
if (this.STACK[i].name == name) break;
if (i != -1) {
var node;
while ((node = this.STACK.pop()).name != name);
this.popNode(node);
} else if (name == 'p' || name == 'br')
this.siblings().push({
name,
attrs: {}
});
this.i = this.data.indexOf('>', this.i);
this.start = this.i + 1;
if (this.i == -1) this.i = this.data.length;
else this.state = this.Text;
}
}
}
module.exports = MpHtmlParser;

View File

@ -0,0 +1,89 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
/* 配置文件 */
// #ifdef MP-WEIXIN
const canIUse = wx.canIUse('editor'); // 高基础库标识,用于兼容
// #endif
module.exports = {
// 过滤器函数
filter: null,
// 代码高亮函数
highlight: null,
// 文本处理函数
onText: null,
blankChar: makeMap(' ,\xA0,\t,\r,\n,\f'),
// 块级标签,将被转为 div
blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,section' + (
// #ifdef MP-WEIXIN
canIUse ? '' :
// #endif
',pre')),
// 将被移除的标签
ignoreTags: makeMap(
'area,base,basefont,canvas,command,frame,input,isindex,keygen,link,map,meta,param,script,source,style,svg,textarea,title,track,use,wbr'
// #ifdef MP-WEIXIN
+ (canIUse ? ',rp' : '')
// #endif
// #ifndef APP-PLUS
+ ',embed,iframe'
// #endif
),
// 只能被 rich-text 显示的标签
richOnlyTags: makeMap('a,colgroup,fieldset,legend,picture,table'
// #ifdef MP-WEIXIN
+ (canIUse ? ',bdi,bdo,caption,rt,ruby' : '')
// #endif
),
// 自闭合的标签
selfClosingTags: makeMap(
'area,base,basefont,br,col,circle,ellipse,embed,frame,hr,img,input,isindex,keygen,line,link,meta,param,path,polygon,rect,source,track,use,wbr'
),
// 信任的属性
trustAttrs: makeMap(
'align,alt,app-id,author,autoplay,border,cellpadding,cellspacing,class,color,colspan,controls,data-src,dir,face,height,href,id,ignore,loop,media,muted,name,path,poster,rowspan,size,span,src,start,style,type,unit-id,width,xmlns'
),
// bool 型的属性
boolAttrs: makeMap('autoplay,controls,ignore,loop,muted'),
// 信任的标签
trustTags: makeMap(
'a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'
// #ifdef MP-WEIXIN
+ (canIUse ? ',bdi,bdo,caption,pre,rt,ruby' : '')
// #endif
// #ifdef APP-PLUS
+ ',embed,iframe'
// #endif
),
// 默认的标签样式
userAgentStyles: {
address: 'font-style:italic',
big: 'display:inline;font-size:1.2em',
blockquote: 'background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px',
caption: 'display:table-caption;text-align:center',
center: 'text-align:center',
cite: 'font-style:italic',
dd: 'margin-left:40px',
img: 'max-width:100%',
mark: 'background-color:yellow',
picture: 'max-width:100%',
pre: 'font-family:monospace;white-space:pre;overflow:scroll',
s: 'text-decoration:line-through',
small: 'display:inline;font-size:0.8em',
u: 'text-decoration:underline'
}
}
function makeMap(str) {
var map = {},
list = str.split(',');
for (var i = list.length; i--;)
map[list[i]] = true;
return map;
}

View File

@ -0,0 +1,44 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
var inlineTags = {
abbr: 1,
b: 1,
big: 1,
code: 1,
del: 1,
em: 1,
i: 1,
ins: 1,
label: 1,
q: 1,
small: 1,
span: 1,
strong: 1
}
export default {
// 从顶层标签的样式中取出一些给 rich-text
getStyle: function(style) {
if (style) {
var i, j, res = '';
if ((i = style.indexOf('display')) != -1)
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
if ((i = style.indexOf('float')) != -1)
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
return res;
}
},
getNode: function(item) {
return [item];
},
// 是否通过 rich-text 显示
useRichText: function(item) {
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
}
}

View File

@ -0,0 +1,53 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
var inlineTags = {
abbr: 1,
b: 1,
big: 1,
code: 1,
del: 1,
em: 1,
i: 1,
ins: 1,
label: 1,
q: 1,
small: 1,
span: 1,
strong: 1
}
module.exports = {
// 从顶层标签的样式中取出一些给 rich-text
getStyle: function(style) {
if (style) {
var i, j, res = '';
if ((i = style.indexOf('display')) != -1)
res = style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
if ((i = style.indexOf('float')) != -1)
res += ';' + style.substring(i, (j = style.indexOf(';', i)) == -1 ? style.length : j);
return res;
}
},
// 处理懒加载
getNode: function(item, imgLoad) {
if (!imgLoad && item.attrs.i != '0') {
var img = {
name: 'img',
attrs: JSON.parse(JSON.stringify(item.attrs))
}
delete img.attrs.src;
img.attrs.style += ';width:20px;height:20px';
return [img];
} else return [item];
},
// 是否通过 rich-text 显示
useRichText: function(item) {
return !item.c && !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1;
}
}

View File

@ -0,0 +1,485 @@
<!--
trees 递归显示组件
githubhttps://github.com/jin-yufeng/Parser
docshttps://jin-yufeng.github.io/Parser
插件市场https://ext.dcloud.net.cn/plugin?id=805
authorJinYufeng
update2020/04/13
-->
<template>
<view class="interlayer">
<block v-for="(n, index) in nodes" v-bind:key="index">
<!--图片-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="''+handler.getStyle(n.attrs.style)" :nodes="handler.getNode(n,!lazyLoad||imgLoad)"
:data-attrs="n.attrs" @tap="imgtap" @longpress="imglongtap" />
<!--#endif-->
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
<rich-text v-if="n.name=='img'" :id="n.attrs.id" class="_img" :style="n.attrs.contain" :nodes='[n]' :data-attrs="n.attrs"
@tap="imgtap" @longpress="imglongtap" />
<!--#endif-->
<!--文本-->
<!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
<rich-text v-else-if="n.decode" class="_entity" :nodes="[n]"></rich-text>
<!--#endif-->
<text v-else-if="n.type=='text'" decode>{{n.text}}</text>
<text v-else-if="n.name=='br'">\n</text>
<!--视频-->
<view v-else-if="n.name=='video'">
<view v-if="(!loadVideo||n.lazyLoad)&&!(controls[n.attrs.id]&&controls[n.attrs.id].play)" :id="n.attrs.id" :class="'_video '+(n.attrs.class||'')"
:style="n.attrs.style" @tap="_loadVideo" />
<video v-else :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay||(controls[n.attrs.id]&&controls[n.attrs.id].play)"
:controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
:unit-id="n.attrs['unit-id']" :data-id="n.attrs.id" data-from="video" data-source="source" @error="error" @play="play" />
</view>
<!--音频-->
<audio v-else-if="n.name=='audio'" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :autoplay="n.attrs.autoplay"
:controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.attrs.source[(controls[n.attrs.id]&&controls[n.attrs.id].index)||0]"
:data-id="n.attrs.id" data-from="audio" data-source="source" @error="error" @play="play" />
<!--链接-->
<view v-else-if="n.name=='a'" :class="'_a '+(n.attrs.class||'')" hover-class="_hover" :style="n.attrs.style"
:data-attrs="n.attrs" @tap="linkpress">
<trees class="_span" :nodes="n.children" />
</view>
<!--广告按需打开注释-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :unit-id="n.attrs['unit-id']"
data-from="ad" @error="error" />-->
<!--#endif-->
<!--#ifdef MP-BAIDU-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :appid="n.attrs.appid"
:apid="n.attrs.apid" :type="n.attrs.type" data-from="ad" @error="error" />-->
<!--#endif-->
<!--#ifdef APP-PLUS-->
<!--<ad v-else-if="n.name=='ad'" :class="n.attrs.class" :style="n.attrs.style" :adpid="n.attrs.adpid"
data-from="ad" @error="error" />-->
<!--#endif-->
<!--列表-->
<view v-else-if="n.name=='li'" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:flex'">
<view v-if="n.type=='ol'" class="_ol-bef">{{n.num}}</view>
<view v-else class="_ul-bef">
<view v-if="n.floor%3==0" class="_ul-p1"></view>
<view v-else-if="n.floor%3==2" class="_ul-p2" />
<view v-else class="_ul-p1" style="border-radius:50%"></view>
</view>
<!--#ifdef MP-ALIPAY-->
<view class="_li">
<trees :nodes="n.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees class="_li" :nodes="n.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</view>
<!--表格-->
<view v-else-if="n.name=='table'&&n.c" :id="n.attrs.id" :class="n.attrs.class" :style="(n.attrs.style||'')+';display:table'">
<view v-for="(tbody, i) in n.children" v-bind:key="i" :class="tbody.attrs.class" :style="(tbody.attrs.style||'')+(tbody.name[0]=='t'?';display:table-'+(tbody.name=='tr'?'row':'row-group'):'')">
<view v-for="(tr, j) in tbody.children" v-bind:key="j" :class="tr.attrs.class" :style="(tr.attrs.style||'')+(tr.name[0]=='t'?';display:table-'+(tr.name=='tr'?'row':'cell'):'')">
<trees v-if="tr.name=='td'" :nodes="tr.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<block v-else>
<!--#ifdef MP-ALIPAY-->
<view v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')">
<trees :nodes="td.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees v-for="(td, k) in tr.children" v-bind:key="k" :class="td.attrs.class" :style="(td.attrs.style||'')+(td.name[0]=='t'?';display:table-'+(td.name=='tr'?'row':'cell'):'')"
:nodes="td.children" :lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</block>
</view>
</view>
</view>
<!--#ifdef APP-PLUS-->
<iframe v-else-if="n.name=='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder"
:width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
<embed v-else-if="n.name=='embed'" :style="n.attrs.style" :width="n.attrs.width" :height="n.attrs.height" :src="n.attrs.src" />
<!--#endif-->
<!--富文本-->
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
<rich-text v-else-if="handler.useRichText(n)" :id="n.attrs.id" :class="'_p __'+n.name" :nodes="[n]" />
<!--#endif-->
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
<rich-text v-else-if="!(n.c||n.continue)" :id="n.attrs.id" :class="_p" :style="n.attrs.contain" :nodes="[n]" />
<!--#endif-->
<!--#ifdef MP-ALIPAY-->
<view v-else :id="n.attrs.id" :class="'_'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style">
<trees :nodes="n.children" />
</view>
<!--#endif-->
<!--#ifndef MP-ALIPAY-->
<trees v-else :class="(n.attrs.id||'')+' _'+n.name+' '+(n.attrs.class||'')" :style="n.attrs.style" :nodes="n.children"
:lazyLoad="lazyLoad" :loadVideo="loadVideo" />
<!--#endif-->
</block>
</view>
</template>
<script module="handler" lang="wxs" src="./handler.wxs"></script>
<script module="handler" lang="sjs" src="./handler.sjs"></script>
<script>
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEBCRMEB
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
global.Parser = {};
import trees from './trees'
export default {
components: {
trees
},
name: 'trees',
data() {
return {
controls: {},
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
imgLoad: false,
// #endif
// #ifndef APP-PLUS
loadVideo: true
// #endif
}
},
props: {
nodes: Array,
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
lazyLoad: Boolean,
// #endif
// #ifdef APP-PLUS
loadVideo: Boolean
// #endif
},
mounted() {
//
this.top = this.$parent;
while (this.top.$options.name != 'parser') {
if (this.top.top) {
this.top = this.top.top;
break;
}
this.top = this.top.$parent;
}
},
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
beforeDestroy() {
if (this.observer)
this.observer.disconnect();
},
// #endif
methods: {
// #ifndef MP-ALIPAY
play(e) {
if (this.top.videoContexts.length > 1 && this.top.autopause)
for (var i = this.top.videoContexts.length; i--;)
if (this.top.videoContexts[i].id != e.currentTarget.dataset.id)
this.top.videoContexts[i].pause();
},
// #endif
imgtap(e) {
var attrs = e.currentTarget.dataset.attrs;
if (!attrs.ignore) {
var preview = true, data = {
id: e.target.id,
src: attrs.src,
ignore: () => preview = false
};
global.Parser.onImgtap && global.Parser.onImgtap(data);
this.top.$emit('imgtap', data);
if (preview) {
var urls = this.top.imgList,
current = urls[attrs.i] ? parseInt(attrs.i) : (urls = [attrs.src], 0);
uni.previewImage({
current,
urls
})
}
}
},
imglongtap(e) {
var attrs = e.item.dataset.attrs;
if (!attrs.ignore)
this.top.$emit('imglongtap', {
id: e.target.id,
src: attrs.src
})
},
linkpress(e) {
var jump = true,
attrs = e.currentTarget.dataset.attrs;
attrs.ignore = () => jump = false;
global.Parser.onLinkpress && global.Parser.onLinkpress(attrs);
this.top.$emit('linkpress', attrs);
if (jump) {
// #ifdef MP
if (attrs['app-id']) {
return uni.navigateToMiniProgram({
appId: attrs['app-id'],
path: attrs.path
})
}
// #endif
if (attrs.href) {
if (attrs.href[0] == '#') {
if (this.top.useAnchor)
this.top.navigateTo({
id: attrs.href.substring(1)
})
} else if (attrs.href.indexOf('http') == 0 || attrs.href.indexOf('//') == 0) {
// #ifdef APP-PLUS
plus.runtime.openWeb(attrs.href);
// #endif
// #ifndef APP-PLUS
uni.setClipboardData({
data: attrs.href,
success: () =>
uni.showToast({
title: '链接已复制'
})
})
// #endif
} else
uni.navigateTo({
url: attrs.href
})
}
}
},
error(e) {
var context, target = e.currentTarget,
source = target.dataset.from;
if (source == 'video' || source == 'audio') {
// source
var index = this.controls[target.id] ? this.controls[target.id].index + 1 : 1;
if (index < target.dataset.source.length)
this.$set(this.controls, target.id + '.index', index);
if (source == 'video') context = uni.createVideoContext(target.id, this);
}
this.top && this.top.$emit('error', {
source,
target,
errMsg: e.detail.errMsg,
errCode: e.detail.errCode,
context
});
},
_loadVideo(e) {
this.$set(this.controls, e.currentTarget.id, {
play: true,
index: 0
})
}
}
}
</script>
<style>
/* 在这里引入自定义样式 */
/* 链接和图片效果 */
._a {
display: inline;
color: #366092;
word-break: break-all;
padding: 1.5px 0 1.5px 0;
}
._hover {
opacity: 0.7;
text-decoration: underline;
}
._img {
display: inline-block;
text-indent: 0;
}
/* #ifdef MP-WEIXIN */
:host {
display: inline;
}
/* #endif */
/* #ifdef MP */
.interlayer {
align-content: inherit;
align-items: inherit;
display: inherit;
flex-direction: inherit;
flex-wrap: inherit;
justify-content: inherit;
width: 100%;
white-space: inherit;
}
/* #endif */
._b,
._strong {
font-weight: bold;
}
._blockquote,
._div,
._p,
._ol,
._ul,
._li {
display: block;
}
._code {
font-family: monospace;
}
._del {
text-decoration: line-through;
}
._em,
._i {
font-style: italic;
}
._h1 {
font-size: 2em;
}
._h2 {
font-size: 1.5em;
}
._h3 {
font-size: 1.17em;
}
._h5 {
font-size: 0.83em;
}
._h6 {
font-size: 0.67em;
}
._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
display: block;
font-weight: bold;
}
._ins {
text-decoration: underline;
}
._li {
flex: 1;
width: 0;
}
._ol-bef {
margin-right: 5px;
text-align: right;
width: 36px;
}
._ul-bef {
line-height: normal;
margin: 0 12px 0 23px;
}
._ol-bef,
._ul_bef {
flex: none;
user-select: none;
}
._ul-p1 {
display: inline-block;
height: 0.3em;
line-height: 0.3em;
overflow: hidden;
width: 0.3em;
}
._ul-p2 {
border: 0.05em solid black;
border-radius: 50%;
display: inline-block;
height: 0.23em;
width: 0.23em;
}
._q::before {
content: '"';
}
._q::after {
content: '"';
}
._sub {
font-size: smaller;
vertical-align: sub;
}
._sup {
font-size: smaller;
vertical-align: super;
}
/* #ifndef MP-WEIXIN */
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
display: inline;
}
/* #endif */
/* #ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY */
.__bdo,
.__bdi,
.__ruby,
.__rt,
._entity {
display: inline-block;
}
/* #endif */
._video {
background-color: black;
display: inline-block;
height: 225px;
position: relative;
width: 300px;
}
._video::after {
border-color: transparent transparent transparent white;
border-style: solid;
border-width: 15px 0 15px 30px;
content: '';
left: 50%;
margin: -15px 0 0 -15px;
position: absolute;
top: 50%;
}
</style>

120
components/return/index.vue Normal file
View File

@ -0,0 +1,120 @@
<template>
<view class="contentgb">
<view class="iconfont icon-xiangzuo" v-if="isshow" style="margin-top: 10rpx;color: #fff;margin-left: 30rpx;" @click="close">
</view>
<view class="name" v-if="isshow">
{{name}}
</view>
<view class="return_top">
<view class="z-bootm-img1" @click="returnbom()">
<image src="@/static/images/fb1.png" mode="aspectFit"></image>
</view>
<view class="z-bootm-l"></view>
<view class="z-bootm-img2" @click="returnbom()">
<image src="@/static/images/fb2.png" mode="aspectFit"></image>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'retuntop',
props: {
isshow: {
type: Boolean
},
name: {
type: String
}
},
data() {
return {
}
},
mounted() {
console.log(this.isshow)
},
methods: {
close(){
uni.navigateBack({
delta:0
})
},
returnbom() {
uni.sendHostEvent('closeApp', (ret) => {
//
console.log('关闭应用' + JSON.stringify(ret));
});
}
}
}
</script>
<style lang="scss" scoped>
.contentgb {
display: flex;
justify-content: space-between;
.name {
font-size: 35rpx;
font-family: Source Han Sans CN-Medium, Source Han Sans CN;
font-weight: 500;
color: #FFFFFF;
margin-top: 5rpx;
}
.return_top {
width: 166rpx;
height: 56rpx;
background: rgba(255, 255, 255, 0.6);
border-radius: 44rpx 44rpx;
margin-right: 30rpx;
position: relative;
.z-bootm-img1 {
width: 41rpx;
height: 13rpx;
position: absolute;
top: 5rpx;
left: 25rpx;
image {
width: 100%;
height: 100%;
}
}
.z-bootm-l {
width: 1px;
height: 32rpx;
background: rgba(0, 0, 0, 0.2);
margin: auto 0;
position: absolute;
top: 10rpx;
left: 85rpx;
}
.z-bootm-img2 {
width: 38rpx;
height: 34rpx;
margin-top: -15rpx;
margin-left: -15rpx;
position: absolute;
right: 25rpx;
top: 25rpx;
image {
width: 100%;
height: 100%;
}
}
}
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,742 @@
<template>
<view class="w-picker-view">
<picker-view v-if="fields=='year'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='month'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='day'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='hour'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='minute'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
<picker-view v-if="fields=='second'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{
years:[],
months:[],
days:[],
hours:[],
minutes:[],
seconds:[]
},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
startYear:{
type:[String,Number],
default:""
},
endYear:{
type:[String,Number],
default:""
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
disabledAfter:{//
type:Boolean,
default:false
},
fields:{
type:String,
default:"day"
}
},
watch:{
fields(val){
this.initData();
},
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg,example
switch(this.fields){
case "year":
strReg=/^\d{4}$/;
example="2019";
break;
case "month":
strReg=/^\d{4}-\d{2}$/;
example="2019-02";
break;
case "day":
strReg=/^\d{4}-\d{2}-\d{2}$/;
example="2019-02-01";
break;
case "hour":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}(:\d{2}){1,2}?$/;
example="2019-02-01 18:00:00或2019-02-01 18";
break;
case "minute":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2}){0,1}?$/;
example="2019-02-01 18:06:00或2019-02-01 18:06";
break;
case "second":
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
example="2019-02-01 18:06:01";
break;
}
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day,hour,minute){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let months=[],days=[],hours=[],minutes=[],seconds=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
let hoursLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)?24:curHour+1):24;
let minutesLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour)?60:curMinute+1):60;
let secondsLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour||minute*1<curMinute)?60:curSecond+1):60;
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
for(let hour=0;hour<hoursLen;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<minutesLen;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<secondsLen;second++){
seconds.push(this.formatNum(second));
}
return{
months,
days,
hours,
minutes,
seconds
}
},
isLeapYear (Year) {
if (((Year % 4)==0) && ((Year % 100)!=0) || ((Year % 400)==0)) {
return true;
} else {
return false;
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let fields=this.fields;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonthdays=curDate.curMonthdays;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let defaultDate=this.getDefaultDate();
let startYear=this.getStartDate().getFullYear();
let endYear=this.getEndDate().getFullYear();
//year,month,day,hour;,
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
let year=dVal[0]*1;
let month=dVal[1]*1;
let day=dVal[2]*1;
let hour=dVal[3]*1;
let minute=dVal[4]*1;
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
let hoursLen=disabledAfter?((year<curYear||month<curMonth||day<curDay)?24:curHour+1):24;
let minutesLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour)?60:curMinute+1):60;
let secondsLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour||minute<curMinute)?60:curSecond+1):60;
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
years.push(year.toString())
}
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
}
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
for(let hour=0;hour<hoursLen;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<minutesLen;minute++){
minutes.push(this.formatNum(minute));
}
// for(let second=0;second<(disabledAfter?curDate.curSecond+1:60);second++){
// seconds.push(this.formatNum(second));
// }
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return {
years,
months,
days,
hours,
minutes,
seconds
}
},
getCurrenDate(){
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth()+1;
let curMonthdays=new Date(curYear,curMonth,0).getDate();
let curDay=curDate.getDate();
let curHour=curDate.getHours();
let curMinute=curDate.getMinutes();
let curSecond=curDate.getSeconds();
return{
curDate,
curYear,
curMonth,
curMonthdays,
curDay,
curHour,
curMinute,
curSecond
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getStartDate(){
let start=this.startYear;
let startDate="";
let reg=/-/g;
if(start){
startDate=new Date(start+"/01/01");
}else{
startDate=new Date("1970/01/01");
}
return startDate;
},
getEndDate(){
let end=this.endYear;
let reg=/-/g;
let endDate="";
if(end){
endDate=new Date(end+"/12/01");
}else{
endDate=new Date();
}
return endDate;
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let hour=this.formatNum(aDate.getHours());
let minute=this.formatNum(aDate.getMinutes());
let second=this.formatNum(aDate.getSeconds());
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[year,month,day,hour,minute,second]
}else{
switch(this.fields){
case "year":
dVal=value?[value]:[];
break;
case "month":
dVal=value?value.split("-"):[];
break;
case "day":
dVal=value?value.split("-"):[];
break;
case "hour":
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
break;
case "minute":
dVal=value?[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")]:[];
break;
case "second":
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
break;
}
}
}else{
dVal=[year,month,day,hour,minute,second]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",year,month,day,hour,minute,second,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curMonthdays=curDate.curMonthdays;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
let dateData=[];
dVal=this.getDval();
startDate=this.getStartDate();
endDate=this.getEndDate();
startYear=startDate.getFullYear();
startMonth=startDate.getMonth();
startDay=startDate.getDate();
endYear=endDate.getFullYear();
endMonth=endDate.getMonth();
endDay=endDate.getDate();
dateData=this.getData(dVal);
years=dateData.years;
months=dateData.months;
days=dateData.days;
hours=dateData.hours;
minutes=dateData.minutes;
seconds=dateData.seconds;
switch(this.fields){
case "year":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
]:(curFlag?[
years.indexOf(curYear+'')
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
]);
range={years};
year=dVal[0]?dVal[0]:years[0];
result=full=`${year}`;
obj={
year
}
break;
case "month":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth))
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
]);
range={years,months};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
result=full=`${year+'-'+month}`;
obj={
year,
month
}
break;
case "day":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
]);
range={years,months,days};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
result=full=`${year+'-'+month+'-'+day}`;
obj={
year,
month,
day
}
break;
case "hour":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
]);
range={years,months,days,hours};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
result=`${year+'-'+month+'-'+day+' '+hour}`;
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
obj={
year,
month,
day,
hour
}
break;
case "minute":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
minutes.indexOf(this.formatNum(curMinute)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
]);
range={years,months,days,hours,minutes};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
minute=dVal[4]?dVal[4]:minutes[0];
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
obj={
year,
month,
day,
hour,
minute
}
break;
case "second":
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
hours.indexOf(this.formatNum(curHour)),
minutes.indexOf(this.formatNum(curMinute)),
seconds.indexOf(this.formatNum(curSecond)),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
]);
range={years,months,days,hours,minutes,seconds};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
hour=dVal[3]?dVal[3]:hours[0];
minute=dVal[4]?dVal[4]:minutes[0];
second=dVal[5]?dVal[5]:seconds[0];
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
obj={
year,
month,
day,
hour,
minute,
second
}
break;
default:
range={years,months,days};
break;
}
this.range=range;
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
});
this.$nextTick(()=>{
this.pickVal=pickVal;
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let year="",month="",day="",hour="",minute="",second="";
let result="",full="",obj={};
let months=null,days=null,hours=null,minutes=null,seconds=null;
let disabledAfter=this.disabledAfter;
let leapYear=false,resetData={};
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
hour=(arr[3]||arr[3]==0)?data.hours[arr[3]]||data.hours[data.hours.length-1]:"";
minute=(arr[4]||arr[4]==0)?data.minutes[arr[4]]||data.minutes[data.minutes.length-1]:"";
second=(arr[5]||arr[5]==0)?data.seconds[arr[5]]||data.seconds[data.seconds.length-1]:"";
resetData=this.resetData(year,month,day,hour,minute);//;
leapYear=this.isLeapYear(year);//;
switch(this.fields){
case "year":
result=full=`${year}`;
obj={
year
};
break;
case "month":
result=full=`${year+'-'+month}`;
if(this.disabledAfter)months=resetData.months;
if(months)this.range.months=months;
obj={
year,
month
}
break;
case "day":
result=full=`${year+'-'+month+'-'+day}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
obj={
year,
month,
day
}
break;
case "hour":
result=`${year+'-'+month+'-'+day+' '+hour}`;
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
obj={
year,
month,
day,
hour
}
break;
case "minute":
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
minutes=resetData.minutes;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
if(minutes)this.range.minutes=minutes;
obj={
year,
month,
day,
hour,
minute
};
break;
case "second":
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
hours=resetData.hours;
minutes=resetData.minutes;
//seconds=resetData.seconds;
}else{
if(leapYear||(month!=this.checkObj.month)||month==2){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(hours)this.range.hours=hours;
if(minutes)this.range.minutes=minutes;
//if(seconds)this.range.seconds=seconds;
obj={
year,
month,
day,
hour,
minute,
second
}
break;
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,345 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.sections" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
startYear:{
type:String,
default:""
},
endYear:{
type:String,
default:""
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
disabledAfter:{//
type:Boolean,
default:false
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2} [\u4e00-\u9fa5]{2}$/,example;
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let months=[],days=[],sections=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
sections=["上午","下午"];
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
if(sectionFlag){
sections=["上午"];
}
return{
months,
days,
sections
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonthdays=curDate.curMonthdays;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let defaultDate=this.getDefaultDate();
let startYear=this.getStartDate().getFullYear();
let endYear=this.getEndDate().getFullYear();
let years=[],months=[],days=[],sections=[];
let year=dVal[0]*1;
let month=dVal[1]*1;
let day=dVal[2]*1;
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
years.push(year.toString())
}
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
}
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
if(sectionFlag){
sections=["下午"];
}else{
sections=["上午","下午"];
}
return {
years,
months,
days,
sections
}
},
getCurrenDate(){
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth()+1;
let curMonthdays=new Date(curYear,curMonth,0).getDate();
let curDay=curDate.getDate();
let curHour=curDate.getHours();
let curSection="上午";
if(curHour>=12){
curSection="下午";
}
return{
curDate,
curYear,
curMonth,
curMonthdays,
curDay,
curHour,
curSection
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.split(" ")[0].replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getStartDate(){
let start=this.startYear;
let startDate="";
let reg=/-/g;
if(start){
startDate=new Date(start+"/01/01");
}else{
startDate=new Date("1970/01/01");
}
return startDate;
},
getEndDate(){
let end=this.endYear;
let reg=/-/g;
let endDate="";
if(end){
endDate=new Date(end+"/12/31");
}else{
endDate=new Date();
}
return endDate;
},
getDval(){
let value=this.value;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let hour=aDate.getHours();
let section="上午";
if(hour>=12)section="下午";
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[year,month,day,section]
}else{
let v=value.split(" ");
dVal=[...v[0].split("-"),v[1]];
}
}else{
dVal=[year,month,day,section]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let years=[],months=[],days=[],sections=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",year,month,day,section,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let curDate=this.getCurrenDate();
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curMonthdays=curDate.curMonthdays;
let curDay=curDate.curDay;
let curSection=curDate.curSection;
let dateData=[];
dVal=this.getDval();
startDate=this.getStartDate();
endDate=this.getEndDate();
startYear=startDate.getFullYear();
startMonth=startDate.getMonth();
startDay=startDate.getDate();
endYear=endDate.getFullYear();
endMonth=endDate.getMonth();
endDay=endDate.getDate();
dateData=this.getData(dVal);
years=dateData.years;
months=dateData.months;
days=dateData.days;
sections=dateData.sections;
pickVal=disabledAfter?[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&sections.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
]:(curFlag?[
years.indexOf(curYear+''),
months.indexOf(this.formatNum(curMonth)),
days.indexOf(this.formatNum(curDay)),
sections.indexOf(curSection),
]:[
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
dVal[3]&&sections.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
]);
range={years,months,days,sections};
year=dVal[0]?dVal[0]:years[0];
month=dVal[1]?dVal[1]:months[0];
day=dVal[2]?dVal[2]:days[0];
section=dVal[3]?dVal[3]:sections[0];
result=full=`${year+'-'+month+'-'+day+' '+section}`;
obj={
year,
month,
day,
section
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let year="",month="",day="",section="";
let result="",full="",obj={};
let months=null,days=null,sections=null;
let disabledAfter=this.disabledAfter;
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
section=(arr[3]||arr[3]==0)?data.sections[arr[3]]||data.sections[data.sections.length-1]:"";
result=full=`${year+'-'+month+'-'+day+' '+section}`;
let resetData=this.resetData(year,month,day);
if(this.disabledAfter){
months=resetData.months;
days=resetData.days;
sections=resetData.sections;
}else{
if(year%4==0||(month!=this.checkObj.month)){
days=resetData.days;
}
}
if(months)this.range.months=months;
if(days)this.range.days=days;
if(sections)this.range.sections=sections;
obj={
year,
month,
day,
section
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,274 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column v-for="(group,gIndex) in range" :key="gIndex">
<view class="w-picker-item" v-for="(item,index) in group" :key="index">{{item[nodeKey]}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:[],
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[Array,String],
default:""
},
defaultType:{
type:String,
default:"label"
},
options:{
type:Array,
default(){
return []
}
},
defaultProps:{
type:Object,
default(){
return{
lable:"label",
value:"value",
children:"children"
}
}
},
level:{
//
type:[Number,String],
default:2
}
},
computed:{
nodeKey(){
return this.defaultProps.label;
},
nodeVal(){
return this.defaultProps.value;
},
nodeChild(){
return this.defaultProps.children;
}
},
watch:{
value(val){
if(this.options.length!=0){
this.initData();
}
},
options(val){
this.initData();
}
},
created() {
if(this.options.length!=0){
this.initData();
}
},
methods:{
getData(){
//
let options=this.options;
let col1={},col2={},col3={},col4={};
let arr1=options,arr2=[],arr3=[],arr4=[];
let col1Index=0,col2Index=0,col3Index=0,col4Index=0;
let a1="",a2="",a3="",a4="";
let dVal=[],obj={};
let value=this.value;
let data=[];
a1=value[0];
a2=value[1];
if(this.level>2){
a3=value[2];
}
if(this.level>3){
a4=value[3];
};
/*第1列*/
col1Index=arr1.findIndex((v)=>{
return v[this.defaultType]==a1
});
col1Index=value?(col1Index!=-1?col1Index:0):0;
col1=arr1[col1Index];
/*第2列*/
arr2=arr1[col1Index][this.nodeChild];
col2Index=arr2.findIndex((v)=>{
return v[this.defaultType]==a2
});
col2Index=value?(col2Index!=-1?col2Index:0):0;
col2=arr2[col2Index];
/*第3列*/
if(this.level>2){
arr3=arr2[col2Index][this.nodeChild];
col3Index=arr3.findIndex((v)=>{
return v[this.defaultType]==a3;
});
col3Index=value?(col3Index!=-1?col3Index:0):0;
col3=arr3[col3Index];
};
/*第4列*/
if(this.level>3){
arr4=arr3[col4Index][this.nodeChild];
col4Index=arr4.findIndex((v)=>{
return v[this.defaultType]==a4;
});
col4Index=value?(col4Index!=-1?col4Index:0):0;
col4=arr4[col4Index];
};
switch(this.level*1){
case 2:
dVal=[col1Index,col2Index];
obj={
col1,
col2
}
data=[arr1,arr2];
break;
case 3:
dVal=[col1Index,col2Index,col3Index];
obj={
col1,
col2,
col3
}
data=[arr1,arr2,arr3];
break;
case 4:
dVal=[col1Index,col2Index,col3Index,col4Index];
obj={
col1,
col2,
col3,
col4
}
data=[arr1,arr2,arr3,arr4];
break
}
return {
data,
dVal,
obj
}
},
initData(){
let dataData=this.getData();
let data=dataData.data;
let arr1=data[0];
let arr2=data[1];
let arr3=data[2]||[];
let arr4=data[3]||[];
let obj=dataData.obj;
let col1=obj.col1,col2=obj.col2,col3=obj.col3||{},col4=obj.col4||{};
let result="",value=[];
let range=[];
switch(this.level){
case 2:
value=[col1[this.nodeVal],col2[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]}`;
range=[arr1,arr2];
break;
case 3:
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]}`;
range=[arr1,arr2,arr3];
break;
case 4:
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal],col4[this.nodeVal]];
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]+col4[this.nodeKey]}`;
range=[arr1,arr2,arr3,arr4];
break;
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=dataData.dVal;
});
this.$emit("change",{
result:result,
value:value,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let col1Index=arr[0],col2Index=arr[1],col3Index=arr[2]||0,col4Index=arr[3]||0;
let arr1=[],arr2=[],arr3=[],arr4=[];
let col1,col2,col3,col4,obj={};
let result="",value=[];
arr1=this.options;
arr2=(arr1[col1Index]&&arr1[col1Index][this.nodeChild])||arr1[arr1.length-1][this.nodeChild]||[];
col1=arr1[col1Index]||arr1[arr1.length-1]||{};
col2=arr2[col2Index]||arr2[arr2.length-1]||{};
if(this.level>2){
arr3=(arr2[col2Index]&&arr2[col2Index][this.nodeChild])||arr2[arr2.length-1][this.nodeChild];
col3=arr3[col3Index]||arr3[arr3.length-1]||{};
}
if(this.level>3){
arr4=(arr3[col3Index]&&arr3[col3Index][this.nodeChild])||arr3[arr3.length-1][this.nodeChild]||[];
col4=arr4[col4Index]||arr4[arr4.length-1]||{};
}
switch(this.level){
case 2:
obj={
col1,
col2
}
this.range=[arr1,arr2];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||''];
break;
case 3:
obj={
col1,
col2,
col3
}
this.range=[arr1,arr2,arr3];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||''];
break;
case 4:
obj={
col1,
col2,
col3,
col4
}
this.range=[arr1,arr2,arr3,arr4];
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')+(col4[this.nodeKey]||'')}`;
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||'',col4[this.nodeVal]||''];
break;
}
this.checkObj=obj;
this.pickVal=arr;
this.$emit("change",{
result:result,
value:value,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,344 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fyears" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fmonths" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.fdays" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex1">
<view class="w-picker-item">-</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tyears" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tmonths" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column class="w-picker-flex2">
<view class="w-picker-item" v-for="(item,index) in range.tdays" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array],
default(){
return []
}
},
current:{//
type:Boolean,
default:false
},
startYear:{
type:[String,Number],
default:1970
},
endYear:{
type:[String,Number],
default:new Date().getFullYear()
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2}$/,example="2020-04-03";
if(!strReg.test(value[0])||!strReg.test(value[1])){
console.log(new Error("请传入与mode匹配的value值例["+example+","+example+"]"))
}
return strReg.test(value[0])&&strReg.test(value[1]);
},
resetToData(fmonth,fday,tyear,tmonth){
let range=this.range;
let tmonths=[],tdays=[];
let yearFlag=tyear!=range.tyears[0];
let monthFlag=tyear!=range.tyears[0]||tmonth!=range.tmonths[0];
let ttotal=new Date(tyear,tmonth,0).getDate();
for(let i=yearFlag?1:fmonth*1;i<=12;i++){
tmonths.push(this.formatNum(i))
}
for(let i=monthFlag?1:fday*1;i<=ttotal;i++){
tdays.push(this.formatNum(i))
}
return{
tmonths,
tdays
}
},
resetData(fyear,fmonth,fday,tyear,tmonth){
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
let startYear=this.startYear;
let endYear=this.endYear;
let ftotal=new Date(fyear,fmonth,0).getDate();
let ttotal=new Date(tyear,tmonth,0).getDate();
for(let i=startYear*1;i<=endYear;i++){
fyears.push(this.formatNum(i))
}
for(let i=1;i<=12;i++){
fmonths.push(this.formatNum(i))
}
for(let i=1;i<=ftotal;i++){
fdays.push(this.formatNum(i))
}
for(let i=fyear*1;i<=endYear;i++){
tyears.push(this.formatNum(i))
}
for(let i=fmonth*1;i<=12;i++){
tmonths.push(this.formatNum(i))
}
for(let i=fday*1;i<=ttotal;i++){
tdays.push(this.formatNum(i))
}
return {
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays
}
},
getData(dVal){
let start=this.startYear*1;
let end=this.endYear*1;
let value=dVal;
let flag=this.current;
let aToday=new Date();
let tYear,tMonth,tDay,tHours,tMinutes,tSeconds,pickVal=[];
let initstartDate=new Date(start.toString());
let endDate=new Date(end.toString());
if(start>end){
initstartDate=new Date(end.toString());
endDate=new Date(start.toString());
};
let startYear=initstartDate.getFullYear();
let startMonth=initstartDate.getMonth()+1;
let endYear=endDate.getFullYear();
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[],returnArr=[],startDVal=[],endDVal=[];
let curMonth=flag?value[1]*1:(startDVal[1]*1+1);
let curMonth1=flag?value[5][1]*1:(value[5]*1+1);
let totalDays=new Date(value[0],value[1],0).getDate();
let totalDays1=new Date(value[4],value[5],0).getDate();
for(let s=startYear;s<=endYear;s++){
fyears.push(this.formatNum(s));
};
for(let m=1;m<=12;m++){
fmonths.push(this.formatNum(m));
};
for(let d=1;d<=totalDays;d++){
fdays.push(this.formatNum(d));
};
for(let s=value[0]*1;s<=endYear;s++){
tyears.push(this.formatNum(s));
};
if(value[4]*1>value[0]*1){
for(let m=1;m<=12;m++){
tmonths.push(this.formatNum(m));
};
for(let d=1;d<=totalDays1;d++){
tdays.push(this.formatNum(d));
};
}else{
for(let m=value[1]*1;m<=12;m++){
tmonths.push(this.formatNum(m));
};
for(let d=value[2]*1;d<=totalDays1;d++){
tdays.push(this.formatNum(d));
};
};
pickVal=[
fyears.indexOf(value[0])==-1?0:fyears.indexOf(value[0]),
fmonths.indexOf(value[1])==-1?0:fmonths.indexOf(value[1]),
fdays.indexOf(value[2])==-1?0:fdays.indexOf(value[2]),
0,
tyears.indexOf(value[4])==-1?0:tyears.indexOf(value[4]),
tmonths.indexOf(value[5])==-1?0:tmonths.indexOf(value[5]),
tdays.indexOf(value[6])==-1?0:tdays.indexOf(value[6])
];
return {
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays,
pickVal
}
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let fyear=this.formatNum(aDate.getFullYear());
let fmonth=this.formatNum(aDate.getMonth()+1);
let fday=this.formatNum(aDate.getDate());
let tyear=this.formatNum(aDate.getFullYear());
let tmonth=this.formatNum(aDate.getMonth()+1);
let tday=this.formatNum(aDate.getDate());
if(value&&value.length>0){
let flag=this.checkValue(value);
if(!flag){
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
}else{
dVal=[...value[0].split("-"),"-",...value[1].split("-")];
}
}else{
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
}
return dVal;
},
initData(){
let range=[],pickVal=[];
let result="",full="",obj={};
let dVal=this.getDval();
let dateData=this.getData(dVal);
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
let fyear,fmonth,fday,tyear,tmonth,tday;
pickVal=dateData.pickVal;
fyears=dateData.fyears;
fmonths=dateData.fmonths;
fdays=dateData.fdays;
tyears=dateData.tyears;
tmonths=dateData.tmonths;
tdays=dateData.tdays;
range={
fyears,
fmonths,
fdays,
tyears,
tmonths,
tdays,
}
fyear=range.fyears[pickVal[0]];
fmonth=range.fmonths[pickVal[1]];
fday=range.fdays[pickVal[2]];
tyear=range.tyears[pickVal[4]];
tmonth=range.tmonths[pickVal[5]];
tday=range.tdays[pickVal[6]];
obj={
fyear,
fmonth,
fday,
tyear,
tmonth,
tday
}
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:result.split("至"),
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let result="",full="",obj={};
let year="",month="",day="",hour="",minute="",second="",note=[],province,city,area;
let checkObj=this.checkObj;
let days=[],months=[],endYears=[],endMonths=[],endDays=[],startDays=[];
let mode=this.mode;
let col1,col2,col3,d,a,h,m;
let xDate=new Date().getTime();
let range=this.range;
let fyear=range.fyears[arr[0]]||range.fyears[range.fyears.length-1];
let fmonth=range.fmonths[arr[1]]||range.fmonths[range.fmonths.length-1];
let fday=range.fdays[arr[2]]||range.fdays[range.fdays.length-1];
let tyear=range.tyears[arr[4]]||range.tyears[range.tyears.length-1];
let tmonth=range.tmonths[arr[5]]||range.tmonths[range.tmonths.length-1];
let tday=range.tdays[arr[6]]||range.tdays[range.tdays.length-1];
let resetData=this.resetData(fyear,fmonth,fday,tyear,tmonth);
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth||fday!=checkObj.fday){
arr[4]=0;
arr[5]=0;
arr[6]=0;
range.tyears=resetData.tyears;
range.tmonths=resetData.tmonths;
range.tdays=resetData.tdays;
tyear=range.tyears[0];
checkObj.tyears=range.tyears[0];
tmonth=range.tmonths[0];
checkObj.tmonths=range.tmonths[0];
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
}
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth){
range.fdays=resetData.fdays;
};
if(tyear!=checkObj.tyear){
arr[5]=0;
arr[6]=0;
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
range.tmonths=toData.tmonths;
range.tdays=toData.tdays;
tmonth=range.tmonths[0];
checkObj.tmonths=range.tmonths[0];
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
};
if(tmonth!=checkObj.tmonth){
arr[6]=0;
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
range.tdays=toData.tdays;
tday=range.tdays[0];
checkObj.tdays=range.tdays[0];
};
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
obj={
fyear,fmonth,fday,tyear,tmonth,tday
}
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=arr;
})
this.$emit("change",{
result:result,
value:result.split("至"),
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,183 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.provinces" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.citys" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column v-if="!hideArea">
<view class="w-picker-item" v-for="(item,index) in range.areas" :key="index">{{item.label}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
import areaData from "./areadata/areadata.js"
export default {
data() {
return {
pickVal:[],
range:{
provinces:[],
citys:[],
areas:[]
},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[Array,String],
default:""
},
defaultType:{
type:String,
default:"label"
},
hideArea:{
type:Boolean,
default:false
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
getData(){
//
let provinces=areaData;
let dVal=[];
let value=this.value;
let a1=value[0];//
let a2=value[1];//
let a3=value[2];//
let province,city,area;
let provinceIndex=provinces.findIndex((v)=>{
return v[this.defaultType]==a1
});
provinceIndex=value?(provinceIndex!=-1?provinceIndex:0):0;
let citys=provinces[provinceIndex].children;
let cityIndex=citys.findIndex((v)=>{
return v[this.defaultType]==a2
});
cityIndex=value?(cityIndex!=-1?cityIndex:0):0;
let areas=citys[cityIndex].children;
let areaIndex=areas.findIndex((v)=>{
return v[this.defaultType]==a3;
});
areaIndex=value?(areaIndex!=-1?areaIndex:0):0;
dVal=this.hideArea?[provinceIndex,cityIndex]:[provinceIndex,cityIndex,areaIndex];
province=provinces[provinceIndex];
city=citys[cityIndex];
area=areas[areaIndex];
let obj=this.hideArea?{
province,
city
}:{
province,
city,
area
}
return this.hideArea?{
provinces,
citys,
dVal,
obj
}:{
provinces,
citys,
areas,
dVal,
obj
}
},
initData(){
let dataData=this.getData();
let provinces=dataData.provinces;
let citys=dataData.citys;
let areas=this.hideArea?[]:dataData.areas;
let obj=dataData.obj;
let province=obj.province,city=obj.city,area=this.hideArea?{}:obj.area;
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
this.range=this.hideArea?{
provinces,
citys,
}:{
provinces,
citys,
areas
};
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=dataData.dVal;
});
this.$emit("change",{
result:result,
value:value,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let provinceIndex=arr[0],cityIndex=arr[1],areaIndex=this.hideArea?0:arr[2];
let provinces=areaData;
let citys=(provinces[provinceIndex]&&provinces[provinceIndex].children)||provinces[provinces.length-1].children||[];
let areas=this.hideArea?[]:((citys[cityIndex]&&citys[cityIndex].children)||citys[citys.length-1].children||[]);
let province=provinces[provinceIndex]||provinces[provinces.length-1],
city=citys[cityIndex]||[citys.length-1],
area=this.hideArea?{}:(areas[areaIndex]||[areas.length-1]);
let obj=this.hideArea?{
province,
city
}:{
province,
city,
area
}
if(this.checkObj.province.label!=province.label){
//;
this.range.citys=citys;
if(!this.hideArea){
this.range.areas=areas;
}
}
if(this.checkObj.city.label!=city.label){
//;
if(!this.hideArea){
this.range.areas=areas;
}
}
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=arr;
})
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
this.$emit("change",{
result:result,
value:value,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,129 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range" :key="index">{{item[nodeKey]}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
props:{
itemHeight:{
type:String,
default:"44px"
},
options:{
type:[Array,Object],
default(){
return []
}
},
value:{
type:String,
default:""
},
defaultType:{
type:String,
default:"label"
},
defaultProps:{
type:Object,
default(){
return{
label:"label",
value:"value"
}
}
}
},
data() {
return {
pickVal:[]
};
},
computed:{
nodeKey(){
return this.defaultProps.label;
},
nodeValue(){
return this.defaultProps.value;
},
range(){
return this.options
}
},
watch:{
value(val){
if(this.options.length!=0){
this.initData();
}
},
options(val){
this.initData();
}
},
created() {
if(this.options.length!=0){
this.initData();
}
},
methods:{
initData(){
let dVal=this.value||"";
let data=this.range;
let pickVal=[0];
let cur=null;
let label="";
let value,idx;
if(this.defaultType==this.nodeValue){
value=data.find((v)=>v[this.nodeValue]==dVal);
idx=data.findIndex((v)=>v[this.nodeValue]==dVal);
}else{
value=data.find((v)=>v[this.nodeKey]==dVal);
idx=data.findIndex((v)=>v[this.nodeKey]==dVal);
}
pickVal=[idx!=-1?idx:0];
this.$nextTick(()=>{
this.pickVal=pickVal;
});
if(this.defaultType==this.nodeValue){
this.$emit("change",{
result:value?value[this.nodeKey]:data[0][this.nodeKey],
value:dVal||data[0][this.nodeKey],
obj:value?value:data[0]
})
}else{
this.$emit("change",{
result:dVal||data[0][this.nodeKey],
value:value?value[this.nodeValue]:data[0][this.nodeValue],
obj:value?value:data[0]
})
}
},
handlerChange(e){
let arr=[...e.detail.value];
let pickVal=[arr[0]||0];
let data=this.range;
let cur=data[arr[0]];
let label="";
let value="";
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:cur[this.nodeKey],
value:cur[this.nodeValue],
obj:cur
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,250 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.dates" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item.label}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
expand:{
type:[Number,String],
default:30
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/,example="2019-12-12 18:05:00或者2019-12-12 18:05";
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curYear=curDate.curYear;
let curMonth=curDate.curMonth;
let curDay=curDate.curDay;
let curHour=curDate.curHour;
let months=[],days=[],sections=[];
let disabledAfter=this.disabledAfter;
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
let totalDays=new Date(year,month,0).getDate();//;
for(let month=1;month<=monthsLen;month++){
months.push(this.formatNum(month));
};
for(let day=1;day<=daysLen;day++){
days.push(this.formatNum(day));
}
return{
months,
days,
sections
}
},
getData(dVal){
//
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let dates=[],hours=[],minutes=[];
let curDate=new Date();
let curYear=curDate.getFullYear();
let curMonth=curDate.getMonth();
let curDay=curDate.getDate();
let aDate=new Date(curYear,curMonth,curDay);
for(let i=0;i<this.expand*1;i++){
aDate=new Date(curYear,curMonth,curDay+i);
let year=aDate.getFullYear();
let month=aDate.getMonth()+1;
let day=aDate.getDate();
let label=year+"-"+this.formatNum(month)+"-"+this.formatNum(day);
switch(i){
case 0:
label="今天";
break;
case 1:
label="明天";
break;
case 2:
label="后天";
break
}
dates.push({
label:label,
value:year+"-"+this.formatNum(month)+"-"+this.formatNum(day)
})
};
for(let i=0;i<24;i++){
hours.push({
label:this.formatNum(i),
value:this.formatNum(i)
})
}
for(let i=0;i<60;i++){
minutes.push({
label:this.formatNum(i),
value:this.formatNum(i)
})
}
return {
dates,
hours,
minutes
}
},
getDefaultDate(){
let value=this.value;
let reg=/-/g;
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
let defaultYear=defaultDate.getFullYear();
let defaultMonth=defaultDate.getMonth()+1;
let defaultDay=defaultDate.getDate();
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
return{
defaultDate,
defaultYear,
defaultMonth,
defaultDay,
defaultDays
}
},
getDval(){
let value=this.value;
let dVal=null;
let aDate=new Date();
let year=this.formatNum(aDate.getFullYear());
let month=this.formatNum(aDate.getMonth()+1);
let day=this.formatNum(aDate.getDate());
let date=this.formatNum(year)+"-"+this.formatNum(month)+"-"+this.formatNum(day);
let hour=aDate.getHours();
let minute=aDate.getMinutes();
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[date,hour,minute]
}else{
let v=value.split(" ");
dVal=[v[0],...v[1].split(":")];
}
}else{
dVal=[date,hour,minute]
}
return dVal;
},
initData(){
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
let dates=[],hours=[],minutes=[];
let dVal=[],pickVal=[];
let value=this.value;
let reg=/-/g;
let range={};
let result="",full="",date,hour,minute,obj={};
let defaultDate=this.getDefaultDate();
let defaultYear=defaultDate.defaultYear;
let defaultMonth=defaultDate.defaultMonth;
let defaultDay=defaultDate.defaultDay;
let defaultDays=defaultDate.defaultDays;
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let dateData=[];
dVal=this.getDval();
dateData=this.getData(dVal);
dates=dateData.dates;
hours=dateData.hours;
minutes=dateData.minutes;
pickVal=[
dates.findIndex(n => n.value == dVal[0])!=-1?dates.findIndex(n => n.value == dVal[0]):0,
hours.findIndex(n => n.value == dVal[1])!=-1?hours.findIndex(n => n.value == dVal[1]):0,
minutes.findIndex(n => n.value == dVal[2])!=-1?minutes.findIndex(n => n.value == dVal[2]):0,
];
range={dates,hours,minutes};
date=dVal[0]?dVal[0]:dates[0].label;
hour=dVal[1]?dVal[1]:hours[0].label;
minute=dVal[2]?dVal[2]:minutes[0].label;
result=full=`${date+' '+hour+':'+minute}`;
obj={
date,
hour,
minute
}
this.range=range;
this.checkObj=obj;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let date="",hour="",minute="";
let result="",full="",obj={};
let disabledAfter=this.disabledAfter;
date=(arr[0]||arr[0]==0)?data.dates[arr[0]]||data.dates[data.dates.length-1]:"";
hour=(arr[1]||arr[1]==0)?data.hours[arr[1]]||data.hours[data.hours.length-1]:"";
minute=(arr[2]||arr[2]==0)?data.minutes[arr[2]]||data.minutes[data.minutes.length-1]:"";
result=full=`${date.label+' '+hour.label+':'+minute.label+':00'}`;
obj={
date,
hour,
minute
}
this.checkObj=obj;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,218 @@
<template>
<view class="w-picker-view">
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column>
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}</view>
</picker-view-column>
<picker-view-column v-if="second">
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
export default {
data() {
return {
pickVal:[],
range:{},
checkObj:{}
};
},
props:{
itemHeight:{
type:String,
default:"44px"
},
value:{
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
second:{
type:Boolean,
default:true
}
},
watch:{
value(val){
this.initData();
}
},
created() {
this.initData();
},
methods:{
formatNum(n){
return (Number(n)<10?'0'+Number(n):Number(n)+'');
},
checkValue(value){
let strReg=/^\d{2}:\d{2}:\d{2}$/,example="18:00:05";
if(!strReg.test(value)){
console.log(new Error("请传入与mode、fields匹配的value值例value="+example+""))
}
return strReg.test(value);
},
resetData(year,month,day,hour,minute){
let curDate=this.getCurrenDate();
let curFlag=this.current;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
for(let hour=0;hour<24;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<60;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return{
hours,
minutes,
seconds
}
},
getData(curDate){
//
let hours=[],minutes=[],seconds=[];
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let fields=this.fields;
let curHour=curDate.curHour;
let curMinute=curDate.curMinute;
let curSecond=curDate.curSecond;
for(let hour=0;hour<24;hour++){
hours.push(this.formatNum(hour));
}
for(let minute=0;minute<60;minute++){
minutes.push(this.formatNum(minute));
}
for(let second=0;second<60;second++){
seconds.push(this.formatNum(second));
}
return this.second?{
hours,
minutes,
seconds
}:{
hours,
minutes
}
},
getCurrenDate(){
let curDate=new Date();
let curHour=curDate.getHours();
let curMinute=curDate.getMinutes();
let curSecond=curDate.getSeconds();
return this.second?{
curHour,
curMinute,
curSecond
}:{
curHour,
curMinute,
}
},
getDval(){
let value=this.value;
let fields=this.fields;
let dVal=null;
let aDate=new Date();
let hour=this.formatNum(aDate.getHours());
let minute=this.formatNum(aDate.getMinutes());
let second=this.formatNum(aDate.getSeconds());
if(value){
let flag=this.checkValue(value);
if(!flag){
dVal=[hour,minute,second]
}else{
dVal=value?value.split(":"):[];
}
}else{
dVal=this.second?[hour,minute,second]:[hour,minute]
}
return dVal;
},
initData(){
let curDate=this.getCurrenDate();
let dateData=this.getData(curDate);
let pickVal=[],obj={},full="",result="",hour="",minute="",second="";
let dVal=this.getDval();
let curFlag=this.current;
let disabledAfter=this.disabledAfter;
let hours=dateData.hours;
let minutes=dateData.minutes;
let seconds=dateData.seconds;
let defaultArr=this.second?[
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0,
dVal[2]&&seconds.indexOf(dVal[2])!=-1?seconds.indexOf(dVal[2]):0
]:[
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0
];
pickVal=disabledAfter?defaultArr:(curFlag?(this.second?[
hours.indexOf(this.formatNum(curDate.curHour)),
minutes.indexOf(this.formatNum(curDate.curMinute)),
seconds.indexOf(this.formatNum(curDate.curSecond)),
]:[
hours.indexOf(this.formatNum(curDate.curHour)),
minutes.indexOf(this.formatNum(curDate.curMinute))
]):defaultArr);
this.range=dateData;
this.checkObj=obj;
hour=dVal[0]?dVal[0]:hours[0];
minute=dVal[1]?dVal[1]:minutes[0];
if(this.second)second=dVal[2]?dVal[2]:seconds[0];
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
this.$nextTick(()=>{
this.pickVal=pickVal;
});
this.$emit("change",{
result:result,
value:full,
obj:obj
})
},
handlerChange(e){
let arr=[...e.detail.value];
let data=this.range;
let hour="",minute="",second="",result="",full="",obj={};
hour=(arr[0]||arr[0]==0)?data.hours[arr[0]]||data.hours[data.hours.length-1]:"";
minute=(arr[1]||arr[1]==0)?data.minutes[arr[1]]||data.minutes[data.minutes.length-1]:"";
if(this.second)second=(arr[2]||arr[2]==0)?data.seconds[arr[2]]||data.seconds[data.seconds.length-1]:"";
obj=this.second?{
hour,
minute,
second
}:{
hour,
minute
};
this.checkObj=obj;
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
this.$emit("change",{
result:result,
value:full,
obj:obj
})
}
}
}
</script>
<style lang="scss">
@import "./w-picker.css";
</style>

View File

@ -0,0 +1,26 @@
.w-picker-flex2{
flex:2;
}
.w-picker-flex1{
flex:1;
}
.w-picker-view {
width: 100%;
height: 476upx;
overflow: hidden;
background-color: rgba(255, 255, 255, 1);
z-index: 666;
}
.d-picker-view{
height: 100%;
}
.w-picker-item {
text-align: center;
width: 100%;
height: 88upx;
line-height: 88upx;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 30upx;
}

View File

@ -0,0 +1,340 @@
<template name="w-picker">
<view class="w-picker" :key="createKey" :data-key="createKey">
<view class="mask" :class="{'visible':visible}" @tap="onCancel" @touchmove.stop.prevent catchtouchmove="true"></view>
<view class="w-picker-cnt" :class="{'visible':visible}">
<view class="w-picker-header" @touchmove.stop.prevent catchtouchmove="true">
<text @tap.stop.prevent="onCancel">取消</text>
<slot></slot>
<text :style="{'color':themeColor}" @tap.stop.prevent="pickerConfirm">确定</text>
</view>
<date-picker
v-if="mode=='date'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:fields="fields"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</date-picker>
<range-picker
v-if="mode=='range'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</range-picker>
<half-picker
v-if="mode=='half'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</half-picker>
<shortterm-picker
v-if="mode=='shortTerm'"
class="w-picker-wrapper"
:startYear="startYear"
:endYear="endYear"
:value="value"
:item-height="itemHeight"
:current="current"
expand="60"
:disabled-after="disabledAfter"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</shortterm-picker>
<time-picker
v-if="mode=='time'"
class="w-picker-wrapper"
:value="value"
:item-height="itemHeight"
:current="current"
:disabled-after="disabledAfter"
:second="second"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</time-picker>
<selector-picker
v-if="mode=='selector'"
class="w-picker-wrapper"
:value="value"
:item-height="itemHeight"
:options="options"
:default-type="defaultType"
:default-props="defaultProps"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</selector-picker>
<region-picker
v-if="mode=='region'"
class="w-picker-wrapper"
:value="value"
:hide-area="hideArea"
:default-type="defaultType"
:item-height="itemHeight"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</region-picker>
<linkage-picker
v-if="mode=='linkage'"
class="w-picker-wrapper"
:value="value"
:options="options"
:level="level"
:default-type="defaultType"
:default-props="defaultProps"
:item-height="itemHeight"
@change="handlerChange"
@touchstart="touchStart"
@touchend="touchEnd">
</linkage-picker>
</view>
</view>
</template>
<script>
import datePicker from "./date-picker.vue"
import rangePicker from "./range-picker.vue"
import halfPicker from "./half-picker.vue"
import shorttermPicker from "./shortterm-picker.vue"
import timePicker from "./time-picker.vue"
import selectorPicker from "./selector-picker.vue"
import regionPicker from "./region-picker.vue"
import linkagePicker from "./linkage-picker.vue"
export default {
name:"w-picker",
components:{
datePicker,
rangePicker,
halfPicker,
timePicker,
selectorPicker,
shorttermPicker,
regionPicker,
linkagePicker
},
props:{
mode:{
type:String,
default:"date"
},
value:{//
type:[String,Array,Number],
default:""
},
current:{//
type:Boolean,
default:false
},
themeColor:{//
type:String,
default:"#f5a200"
},
fields:{//:yearmonthdayhourminutesecond
type:String,
default:"date"
},
disabledAfter:{//
type:Boolean,
default:false
},
second:{//time-picker
type:Boolean,
default:true
},
options:{//selector,region
type:[Array,Object],
default(){
return []
}
},
defaultProps:{//selector,linkagle
type:Object,
default(){
return{
label:"label",
value:"value",
children:"children"
}
}
},
defaultType:{
type:String,
default:"label"
},
hideArea:{//mode=region
type:Boolean,
default:false
},
level:{
//,2-4;
type:[Number,String],
default:2
},
timeout:{//,
type:Boolean,
default:false
},
expand:{//mode=shortterm
type:[Number,String],
default:30
},
startYear:{
type:[String,Number],
default:1970
},
endYear:{
type:[String,Number],
default:new Date().getFullYear()
},
visible:{
type:Boolean,
default:false
}
},
created() {
this.createKey=Math.random()*1000;
},
data() {
return {
itemHeight:`height: ${uni.upx2px(88)}px;`,
result:{},
confirmFlag:true
};
},
methods:{
touchStart(){
if(this.timeout){
this.confirmFlag=false;
}
},
touchEnd(){
if(this.timeout){
setTimeout(()=>{
this.confirmFlag=true;
},500)
}
},
handlerChange(res){
let _this=this;
this.result={...res};
},
show(){
this.$emit("update:visible",true);
},
hide(){
this.$emit("update:visible",false);
},
onCancel(res){
this.$emit("update:visible",false);
this.$emit("cancel");
},
pickerConfirm(){
if(!this.confirmFlag){
return;
};
this.$emit("confirm",this.result);
this.$emit("update:visible",false);
}
}
}
</script>
<style lang="scss">
.w-picker-item {
text-align: center;
width: 100%;
height: 88upx;
line-height: 88upx;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 30upx;
}
.w-picker{
z-index: 888;
.mask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
}
.mask.visible{
visibility: visible;
opacity: 1;
}
.w-picker-cnt {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
background-color: #fff;
}
.w-picker-cnt.visible {
transform: translateY(0);
}
.w-picker-header{
display: flex;
align-items: center;
padding: 0 30upx;
height: 88upx;
background-color: #fff;
position: relative;
text-align: center;
font-size: 32upx;
justify-content: space-between;
border-bottom: solid 1px #eee;
.w-picker-btn{
font-size: 30upx;
}
}
.w-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);
}
}
</style>

57
config/app.js Normal file
View File

@ -0,0 +1,57 @@
let httpApiThree;
let httpApi; // 总域名
let httpApiTwo; // 物流系统域名
const env = 'dev'; // 开发
// const env = 'prod'; // 生产
// const env = 'prew'; // 预上线
// const env = 'local'; // 本地
switch (env) {
case 'prod':
httpApi = 'https://worker-task.lihaink.cn' //正式
httpApiTwo = 'https://logistics.lihaink.cn' //正式环境
httpApiThree = 'https://worker-task.lihaink.cn' //正式
break;
case 'prew':
httpApi = 'https://preview-worker-task.lihaink.cn' //预上线
httpApiThree = 'https://preview-worker-task.lihaink.cn' //预上线
httpApiTwo = 'https://preview-logistics.lihaink.cn' //预上线
break;
case 'local':
httpApi = 'http://192.168.1.12:8001' //预上线
httpApiThree = 'http://192.168.1.12:8001' //预上线
httpApiTwo = 'http://192.168.1.12:8001' //预上线
break;
default:
httpApi = 'https://ceshi-oa.lihaink.cn' //测试
httpApiThree = 'https://ceshi-oa.lihaink.cn' //测试
httpApiTwo = 'https://ceshi-logistics.lihaink.cn' //测试环境
//测试环境
}
module.exports = {
// 请求域名 格式: https://您的域名
HTTP_REQUEST_URL: httpApi,
HTTP_REQUEST_URL_THREE: httpApiThree,
HTTP_REQUEST_URL_TWO: httpApiTwo,
HEADER: {
'content-type': 'application/json',
//#ifdef MP
'Form-type': 'routine',
//#endif
//#ifdef APP-PLUS
'Form-type': 'app',
//#endif
},
// 回话密钥名称 请勿修改此配置
// TOKENNAME: 'X-Token',
TOKENNAME: 'token',
// 缓存时间 0 永久
EXPIRE: 0,
};

41
config/cache.js Normal file
View File

@ -0,0 +1,41 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
module.exports = {
//token
LOGIN_STATUS: 'LOGIN_STATUS_TOKEN',
// uid
UID:'UID',
//<2F>û<EFBFBD>
USER_INFO: 'USER_INFO',
//token<65><6E><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
EXPIRES_TIME: 'EXPIRES_TIME',
//<2F>Ƿ<EFBFBD><C7B7><EFBFBD>Ȩ
WX_AUTH: 'WX_AUTH',
//<2F><><EFBFBD>ں<EFBFBD><DABA><EFBFBD>Ȩcode
STATE_KEY: 'wx_authorize_state',
//<2F>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
LOGINTYPE: 'loginType',
//<2F><><EFBFBD>ں<EFBFBD><DABA><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>
BACK_URL: 'login_back_url',
// С<><D0A1><EFBFBD><EFBFBD>code
STATE_R_KEY: 'roution_authorize_state',
//<2F><>ȨlogoС<6F><D0A1><EFBFBD><EFBFBD>
LOGO_URL: 'LOGO_URL',
//模板缓存
SUBSCRIBE_MESSAGE: 'SUBSCRIBE_MESSAGE',
TIPS_KEY: 'TIPS_KEY',
SPREAD: 'spread',
//缓存经度
CACHE_LONGITUDE: 'LONGITUDE',
//缓存纬度
CACHE_LATITUDE: 'LATITUDE',
}

20
index.html Normal file
View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

104
libs/login.js Normal file
View File

@ -0,0 +1,104 @@
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
import store from "../store";
import Cache from '../utils/cache';
// #ifdef H5
// import { isWeixin } from "../utils";
// import auth from './wechat';
// #endif
import {
LOGIN_STATUS,
USER_INFO,
EXPIRES_TIME,
STATE_R_KEY
} from './../config/cache';
function prePage() {
let pages = getCurrentPages();
console.log(pages)
let prePage = pages[pages.length - 2];
// #ifdef H5
return prePage;
// #endif
//return prePage.$vm;
}
export function toLogin(push, pathLogin) {
store.commit("LOGOUT");
let path = prePage();
if (path) {
path = path.router;
if (path == undefined) {
path = location.pathname + location.search;
}
}
// #ifdef MP
uni.navigateTo({
url: '/page/users/login/login'
})
// #endif
// #ifdef H5
else {
path = location.pathname + location.search;
}
// #endif
if (!pathLogin)
pathLogin = '/page/users/login/login'
Cache.set('login_back_url', path);
uni.navigateTo({
url: '/pages/users/login/login'
})
// #ifdef H5
if (isWeixin()) {
// auth.oAuth(); // 微信授权
uni.navigateTo({
url: '/pages/users/login/login'
})
} else {
if (path !== pathLogin) {
push ? uni.navigateTo({
url: '/pages/users/login/login'
}) : uni.reLaunch({
url: '/pages/users/login/login'
});
}
}
// #endif
// #ifdef APP-PLUS
uni.navigateTo({
url: '/pages/users/login/login',
})
// #endif
}
export function checkLogin() {
let token = Cache.get(LOGIN_STATUS);
let expiresTime = Cache.get(EXPIRES_TIME) || 0;
let newTime = Math.round(new Date() / 1000);
if (expiresTime < newTime || !token) {
Cache.clear(LOGIN_STATUS);
Cache.clear(EXPIRES_TIME);
Cache.clear(USER_INFO);
Cache.clear(STATE_R_KEY);
return false;
} else {
store.commit('UPDATE_LOGIN', token);
let userInfo = Cache.get(USER_INFO, true);
if (userInfo) {
store.commit('UPDATE_USERINFO', userInfo);
}
return true;
}
}

186
libs/routine.js Normal file
View File

@ -0,0 +1,186 @@
import store from '@/store';
import { checkLogin } from './login';
import { login } from '@/api/pubic.js';
import Cache from '@/utils/cache';
import { STATE_R_KEY, USER_INFO, EXPIRES_TIME, LOGIN_STATUS } from '@/config/cache';
class Routine {
constructor() {
this.scopeUserInfo = 'scope.userInfo';
}
async getUserCode() {
let isAuth = await this.isAuth(),
code = '';
if (isAuth)
code = await this.getCode();
return code;
}
/**
* 获取用户信息
*/
getUserInfo() {
let that = this,
code = this.getUserCode();
return new Promise((resolve, reject) => {
uni.getUserInfo({
lang: 'zh_CN',
success(user) {
if (code) user.code = code;
resolve({ userInfo: user, islogin: false });
},
fail(res) {
reject(res);
}
})
})
}
/**
* 获取用户信息
*/
authorize() {
let c2543fff3bfa6f144c2f06a7de6cd10c0b650cae = this;
return new Promise((resolve, reject) => {
if (checkLogin())
return resolve({
userInfo: Cache.get(USER_INFO, true),
islogin: true,
});
uni.authorize({
scope: c2543fff3bfa6f144c2f06a7de6cd10c0b650cae.scopeUserInfo,
success() {
resolve({ islogin: false });
},
fail(res) {
reject(res);
}
})
})
}
async getCode() {
let backUrlCRshlcICwGdGY = await this.getProvider();
return new Promise((resolve, reject) => {
if (Cache.has(STATE_R_KEY)) {
return resolve(Cache.get(STATE_R_KEY));
}
uni.login({
provider: backUrlCRshlcICwGdGY,
success(res) {
if (res.code) Cache.set(STATE_R_KEY, res.code, 10800);
return resolve(res.code);
},
fail() {
return reject(null);
}
})
})
}
/**
* 获取服务供应商
*/
getProvider() {
return new Promise((resolve, reject) => {
uni.getProvider({
service: 'oauth',
success(res) {
resolve(res.provider);
},
fail() {
resolve(false);
}
});
});
}
/**
* 是否授权
*/
isAuth() {
let that = this;
return new Promise((resolve, reject) => {
uni.getSetting({
success(res) {
if (!res.authSetting[that.scopeUserInfo]) {
resolve(true)
} else {
resolve(true);
}
},
fail() {
resolve(false);
}
});
});
}
getUserProfile(code) {
return new Promise((resolve, reject) => {
uni.getUserProfile({
lang: 'zh_CN',
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success(user) {
if (code) user.code = code;
resolve({
userInfo: user,
islogin: false
});
},
fail(res) {
reject(res);
}
})
})
}
/**
* 小程序比较版本信息
* @param v1 当前版本
* @param v2 进行比较的版本
* @return boolen
*
*/
compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
authUserInfo(data) {
return new Promise((resolve, reject) => {
login(data).then(res => {
let time = res.data.expires_time - Cache.time();
store.commit('UPDATE_USERINFO', res.data.user);
store.commit('LOGIN', { token: res.data.token, time: time });
store.commit('SETUID', res.data.user.uid);
Cache.set(EXPIRES_TIME, res.data.expires_time, time);
Cache.set(USER_INFO, res.data.userInfo, time);
return resolve(res);
}).catch(res => {
return reject(res);
})
})
}
}
export default new Routine();

474
libs/uniApi.js Normal file
View File

@ -0,0 +1,474 @@
// import uniCopy from '@/js_sdk/xb-copy/uni-copy.js'; // 拷贝功能插件
// import compressImage from './compressImage.js'; // 解决图片旋转90°问题
// const device = uni.getSystemInfoSync();
// console.log("device:======================== " + JSON.stringify(device));
/*
参数说明
@url
要跳转的目标地址
@opt
要传给目标地址的参数
可在目标页面的onLoad生命周期函数的第一个参数中获取
*/
// 压栈跳转页面
export function navigateTo(type, url, opt) {
// H5端页面跳转目前不支持动画 (浏览器性能限制)
let toUrl = url;
let api = 'navigateTo';
toUrl = opt ? toUrl + '?' + convertObj(opt) : toUrl;
switch (type) {
case 1:
api = 'navigateTo';
break;
case 2:
api = 'redirectTo'; // 关闭当前页,跳转应用内某个页面
break;
case 3:
api = 'reLaunch'; // 关闭所有页面,打开到应用内某个页面
break;
case 4:
api = 'switchTab'; //跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
break;
default:
api = 'navigateTo'
break;
}
uni[api]({
url: toUrl,
animationType: 'slide-in-right',
animationDuration: 200
});
}
// 关闭当前页面并返回上一页面 delta 标识返回几层
export function navigateBack(delta) {
uni.navigateBack({
delta: delta
});
}
// setStorage 将数据存入缓存
export function setStorage(key, val) {
if (typeof val == 'string') {
uni.setStorageSync(key, val);
return val
}
uni.setStorageSync(key, JSON.stringify(val));
}
// getStorage 从缓存中读取数据
export function getStorage(key) {
let uu = uni.getStorageSync(key);
try {
if (typeof JSON.parse(uu) != 'number') {
uu = JSON.parse(uu);
}
} catch (e) {}
return uu;
}
// 删除缓存中的数据
export function removeStorage(key) {
if (key) {
uni.removeStorageSync(key);
}
}
// 将缓存中的数据清空
export function clearStorage() {
try {
uni.clearStorageSync();
} catch (e) {
throw new Error('处理失败');
}
}
// 显示Toast
/*
@title 最多汉字数量7个
@icon success loading none
*/
export function Toast(title, icon = 'none', obj = {}, duration = 700) {
let toastData = {
title: title,
duration: duration,
// position: 'center',
mask: true,
icon: icon ? icon : 'none',
...obj
};
uni.showToast(toastData);
}
/*
显示loading提示框,需要手动隐藏
*/
export function Loading(title = '正在加载...', obj = {}) {
uni.showLoading({
title: title,
mask: true,
...obj
});
}
// 隐藏loading
export function hideLoading() {
try {
uni.hideLoading();
} catch (e) {
//TODO handle the exception
throw new Error('处理失败');
}
}
// 模态框
/*
确定取消按钮的文字颜色可修改
obj 对象中传入 cancelColor : rgb 即可修改取消按钮颜色
obj 对象中传入 confirmColor : rgb 即可修改确认按钮颜色
*/
export function Modal(title = '提示', content = '这是一个模态弹窗!', obj = {
showCancel: true,
cancelText: '取消',
confirmText: '确定'
}) {
// #ifdef APP-PLUS
obj.cancelText = '确定';
obj.confirmText = '取消';
// #endif
return new Promise((reslove, reject) => {
uni.showModal({
title: title,
content: content,
...obj,
success: (res) => {
if (res.confirm) {
reslove()
}
if (res.cancel) {
reject()
}
}
});
})
}
/*
显示操作菜单
@itemList 操作菜单数组
@itemColor 文字颜色
*/
export function ActionSheet(itemList, itemColor = "#000000") {
return new Promise((reslove, reject) => {
uni.showActionSheet({
itemList: itemList,
itemColor: itemColor,
success: (res) => {
reslove(res.tapIndex);
},
fail: function(res) {
reject(res.errMsg);
}
});
})
}
//将页面滚动到目标位置。
export function ScrollTo(ScrollTop) {
uni.pageScrollTo({
scrollTop: ScrollTop,
duration: 300
})
}
// 获取用户信息
export function GetUserInfo() {
return new Promise((reslove, reject) => {
uni.getUserInfo({
success(res) {
console.log(res);
reslove(res);
},
fail(rej) {
reject(rej);
}
})
})
}
// 获取用户授权信息
export function Authorize(scoped = 'scope.userInfo') {
return new Promise((reslove, reject) => {
uni.authorize({
scope: scoped,
success(res) {
reslove(res);
},
fail(rej) {
reject(rej);
}
})
})
}
// 将对象转换成使用 & 连接的字符串
export function convertObj(opt) {
let str = '';
let arr = [];
Object.keys(opt).forEach(item => {
arr.push(`${item}=${opt[item]}`);
})
str = arr.join('&');
return str;
}
// 节流函数
// 节流函数
export function throttle(fn, delay) {
var lastArgs;
var timer;
var delay = delay || 200;
return function(...args) {
lastArgs = args;
if (!timer) {
timer = setTimeout(() => {
timer = null;
fn.apply(this, lastArgs);
}, delay);
}
}
}
// 调起相机
export function chooseImage(count) {
return new Promise((reslove, reject) => {
uni.chooseImage({
count: count, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], //从相册选择
success: (res) => {
reslove(res);
// const tempFilePaths = res.tempFilePaths;
// let tempPathList = [];
// for (let i = 0; i < tempFilePaths.length; i++) {
// const path = tempFilePaths[i];
// const src = await compressImageHandler(path)
// tempPathList.push(src);
// }
// reslove(tempPathList);
},
fail: (rej) => {
reject(rej);
}
});
})
}
// function compressImageHandler(src) {
// // console.log('platform===' + device.platform)
// const tempPath = compressImage(src, device.platform);
// // console.log('tempPath-----' + tempPath);
// return tempPath
// }
//序列化对象和数组
export function serialize(data) {
if (data != null && data != '') {
try {
return JSON.parse(JSON.stringify(data));
} catch (e) {
if (data instanceof Array) {
return [];
}
return {};
}
}
return data;
}
Date.prototype.format = function(fmt) {
let o = {
'M+': this.getMonth() + 1, //月份
'd+': this.getDate(), //日
'h+': this.getHours(), //小时
'm+': this.getMinutes(), //分
's+': this.getSeconds(), //秒
'q+': Math.floor((this.getMonth() + 3) / 3), //季度
S: this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, String(this.getFullYear()).substr(4 - RegExp.$1.length));
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(String(o[k]).length));
}
}
return fmt;
};
//格式化日期
export function formatDate(nS, format) {
//日期格式化
if (!nS) {
return '';
}
format = format || 'yyyy-MM-dd hh:mm:ss';
return new Date(nS).format(format);
}
// 图片转base64
export function pathToBase64(path) {
return new Promise(function(resolve, reject) {
if (typeof window === 'object' && 'document' in window) {
if (typeof FileReader === 'function') {
var xhr = new XMLHttpRequest()
xhr.open('GET', path, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (this.status === 200) {
let fileReader = new FileReader()
fileReader.onload = function(e) {
resolve(e.target.result)
}
fileReader.onerror = reject
fileReader.readAsDataURL(this.response)
}
}
xhr.onerror = reject
xhr.send()
return
}
var canvas = document.createElement('canvas')
var c2x = canvas.getContext('2d')
var img = new Image
img.onload = function() {
canvas.width = img.width
canvas.height = img.height
c2x.drawImage(img, 0, 0)
resolve(canvas.toDataURL())
canvas.height = canvas.width = 0
}
img.onerror = reject
img.src = path
return
}
if (typeof plus === 'object') {
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
entry.file(function(file) {
var fileReader = new plus.io.FileReader()
fileReader.onload = function(data) {
resolve(data.target.result)
}
fileReader.onerror = function(error) {
reject(error)
}
fileReader.readAsDataURL(file)
}, function(error) {
reject(error)
})
}, function(error) {
reject(error)
})
return
}
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
wx.getFileSystemManager().readFile({
filePath: path,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
return
}
reject(new Error('not support'))
})
}
/*
@value 要拷贝的内容
*/
// export function copyText(value) {
// // 条件编译以下代码仅在H5出现
// //#ifdef H5
// return new Promise((reslove, reject) => {
// uniCopy({
// content: value,
// success: (res) => {
// reslove(res);
// },
// error: (e) => {
// reject(res)
// }
// })
// })
// //#endif
// // 以下代码在除H5以外的平台出现
// //#ifndef H5
// //#endif
// }
// 获取本周的第一天
export function showWeekFirstDay() {
var date = new Date();
var weekday = date.getDay() || 7; //获取星期几,getDay()返回值是 0周日 到 6周六 之间的一个整数。0||7为7即weekday的值为1-7
date.setDate(date.getDate() - weekday + 1); //往前算weekday-1年份、月份会自动变化
return formatDate(date, 'yyyy-MM-dd');
}
// 获取本月第一天
export function showMonthFirstDay() {
var MonthFirstDay = new Date().setDate(1);
return formatDate(new Date(MonthFirstDay).getTime(), 'yyyy-MM-dd');
}
var now = new Date(); //当前日期
// var nowDayOfWeek = now.getDay(); //今天本周的第几天
// var nowDay = now.getDate(); //当前日
var nowMonth = now.getMonth(); //当前月
var nowYear = now.getYear(); //当前年
nowYear += (nowYear < 2000) ? 1900 : 0; //
//获得本季度的开始月份
function getQuarterStartMonth() {
var quarterStartMonth = 0;
if (nowMonth < 3) {
quarterStartMonth = 0;
}
if (2 < nowMonth && nowMonth < 6) {
quarterStartMonth = 3;
}
if (5 < nowMonth && nowMonth < 9) {
quarterStartMonth = 6;
}
if (nowMonth > 8) {
quarterStartMonth = 9;
}
return quarterStartMonth;
}
//或的本季度的结束日期
//获得本季度的开始日期
export function getQuarterStartDate() {
var quarterStartDate = new Date(nowYear, getQuarterStartMonth(), 1);
return formatDate(quarterStartDate, 'yyyy-MM-dd');
}
// 删除数组中重复数据
export function unique(data) {
data = data || [];
var n = {}; //存放新的数据
for (var i = 0; i < data.length; i++) {
var v = JSON.stringify(data[i]);
if (typeof(v) == "undefined") {
n[v] = 1;
}
}
data.length = 0;
for (var i in n) {
data[data.length] = i;
}
return data;
}

29
main.js Normal file
View File

@ -0,0 +1,29 @@
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import store from './store'
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App,
store
})
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif

76
manifest.json Normal file
View File

@ -0,0 +1,76 @@
{
"name" : "OAsystem",
"appid" : "__UNI__40723E1",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2"
}

24
package-lock.json generated Normal file
View File

@ -0,0 +1,24 @@
{
"name": "OAsystem",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"crypto-js": "^4.2.0"
}
},
"node_modules/crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
}
},
"dependencies": {
"crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
}
}
}

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"dependencies": {
"crypto-js": "^4.2.0"
}
}

547
pages.json Normal file
View File

@ -0,0 +1,547 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom"
}
},
{
"path": "pages/oaLogin/oaLogin",
"style": {
"navigationBarTitleText": "登录",
"app-plus": {
"titleNView": false,
"bounce": "none"
},
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/oaLogin/editpwd",
"style": {
"navigationBarTitleText": "修改密码",
"app-plus": {
"titleNView": false,
"bounce": "none"
},
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/oaTask/oaTask",
"style": {
"navigationBarTitleText": "任务",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/employees/index",
"style": {
"navigationBarTitleText": "企业员工",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/structure/index",
"style": {
"navigationBarTitleText": "部门架构",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/examine/index",
"style": {
"navigationBarTitleText": "审批"
}
},
{
"path": "pages/appcenter/index",
"style": {
"navigationBarTitleText": "应用中心",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/leaveapplication/index",
"style": {
"navigationBarTitleText": "申请"
}
},
{
"path": "pages/resources/index",
"style": {
"navigationBarTitleText": "人力资源"
}
},
{
"path": "pages/adddepartment/index",
"style": {
"navigationBarTitleText": "添加部门",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/jobtitle/index",
"style": {
"navigationBarTitleText": "岗位职称",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addjobtitle/index",
"style": {
"navigationBarTitleText": "添加岗位",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/personneltransfer/index",
"style": {
"navigationBarTitleText": "人事调动",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addpersonneltransfer/index",
"style": {
"navigationBarTitleText": "添加人事调动",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/resignationprofile/index",
"style": {
"navigationBarTitleText": "离职档案",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/addresignationprofile/index",
"style": {
"navigationBarTitleText": "添加离职档案",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/employees/index",
"style": {
"navigationBarTitleText": "企业员工",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addemployees/index",
"style": {
"navigationBarTitleText": "新增企业员工",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/project/index",
"style": {
"navigationBarTitleText": "项目",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addproject/index",
"style": {
"navigationBarTitleText": "新增项目",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/generalapproval/index",
"style": {
"navigationBarTitleText": "通用审批",
"navigationStyle": "custom"
}
},
{
"path": "pages/addquest/index",
"style": {
"navigationBarTitleText": "新增任务",
"navigationBarBackgroundColor": "#3274F9"
}
},
{
"path": "pages/reimbursementrecord/index",
"style": {
"navigationBarTitleText": "报销打款",
"navigationStyle": "custom"
}
},
{
"path": "pages/reimbursementrecord/index",
"style": {
"navigationBarTitleText": "报销打款",
"navigationBarBackgroundColor": "#3274F9"
}
},
{
"path": "pages/quest/index",
"style": {
"navigationBarTitleText": "任务"
}
},
{
"path": "pages/addworkrecord/index",
"style": {
"navigationBarTitleText": "工作记录",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/workrecord/index",
"style": {
"navigationBarTitleText": "工作记录",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/leave_request/index",
"style": {
"navigationBarTitleText": "审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/leave_request/detail",
"style": {
"navigationBarTitleText": "审批详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},{
"path": "pages/leave_request/bianji",
"style": {
"navigationBarTitleText": "审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/reimbursement/index",
"style": {
"navigationBarTitleText": "报销列表",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/reimbursementapplication/detail",
"style": {
"navigationBarTitleText": "报销详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/reimbursementapplication/index",
"style": {
"navigationBarTitleText": "报销审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/reimbursementapplication/bianji",
"style": {
"navigationBarTitleText": "编辑报销",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}, {
"path": "pages/reimbursementapplication/handle",
"style": {
"navigationBarTitleText": "报销审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},{
"path": "pages/reimbursement/index",
"style": {
"navigationBarTitleText": "审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/invoice/index",
"style": {
"navigationBarTitleText": "发票列表",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/invoice/add",
"style": {
"navigationBarTitleText": "发起发票",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/invoice/detail",
"style": {
"navigationBarTitleText": "发票详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/invoice/handle",
"style": {
"navigationBarTitleText": "发票审批",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/invoice/bianji",
"style": {
"navigationBarTitleText": "编辑发票",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/user/user",
"style": {
"navigationBarTitleText": "我的",
"navigationStyle": "custom"
}
},
{
"path": "pages/financeincome/index",
"style": {
"navigationBarTitleText": "发票开票",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addfinanceincome/index",
"style": {
"navigationBarTitleText": "编辑开票",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/finance/index",
"style": {
"navigationBarTitleText": "发票到账",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/addfinance/index",
"style": {
"navigationBarTitleText": "编辑到账",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#666666",
"selectedColor": "#3274F9",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar_icon/a.png",
"selectedIconPath": "static/tabbar_icon/a-a.png",
"text": "首页"
},
{
"pagePath": "pages/examine/index",
"iconPath": "static/tabbar_icon/b.png",
"selectedIconPath": "static/tabbar_icon/b-b.png",
"text": "审批"
},
{
"pagePath": "pages/oaTask/oaTask",
"iconPath": "static/tabbar_icon/c-c.png",
"selectedIconPath": "static/tabbar_icon/c.png",
"text": "任务"
},
{
"pagePath": "pages/user/user",
"iconPath": "static/tabbar_icon/d-d.png",
"selectedIconPath": "static/tabbar_icon/d.png",
"text": "我的"
}
]
},
"uniIdRouter": {},
"subPackages": [{
"root": "pages/views",
"name": "views",
"pages": [
{
"path": "new_task",
"style": {
"navigationBarTitleText": "新建任务",
"enablePullDownRefresh": false
}
},
{
"path": "com_approve",
"style": {
"navigationBarTitleText": "通用审批",
"enablePullDownRefresh": false
}
}, {
"path": "task_details",
"style": {
"navigationBarTitleText": "任务描述",
"enablePullDownRefresh": false
}
}, {
"path": "leave_request",
"style": {
"navigationBarTitleText": "请假申请",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#0122C7",
"navigationBarTextStyle": "white"
}
}, {
"path": "leave_request",
"style": {
"navigationBarTitleText": "请假申请",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#0122C7",
"navigationBarTextStyle": "white"
}
}
]
},
{
"root": "pages/users",
"name": "users",
"pages": [{
"path": "myInformation/index",
"style": {
"navigationBarTitleText": "个人信息",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "salarydetails/index",
"style": {
"navigationBarTitleText": "工资详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "user_document/index",
"style": {
"navigationBarTitleText": "公司公示文档",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "user_document/detail",
"style": {
"navigationBarTitleText": "公司公示文档详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "article/index",
"style": {
"navigationBarTitleText": "文章列表",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
},
{
"path": "article/detail",
"style": {
"navigationBarTitleText": "文章详情",
"navigationBarBackgroundColor": "#3274F9",
"navigationBarTextStyle": "white"
}
}
]
}
]
}

10
uni.promisify.adaptor.js Normal file
View File

@ -0,0 +1,10 @@
uni.addInterceptor({
returnValue (res) {
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
return res;
}
return new Promise((resolve, reject) => {
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1]));
});
},
});

77
uni.scss Normal file
View File

@ -0,0 +1,77 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量同时无需 import 这个文件
*/
@import '@/uni_modules/uview-ui/theme.scss';
/* 颜色变量 */
$theme-oa-color: #3274F9;
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;