This commit is contained in:
shijing 2022-08-03 16:55:51 +08:00
parent 834401908c
commit 7294adcf94
36 changed files with 5144 additions and 849 deletions

View File

@ -10,80 +10,106 @@ const install = (Vue, vm) => {
id: 2
});
// 此处使用了传入的params参数一切自定义即可
let getUserInfo = (params = {}) => vm.$u.get('/system/user/info/', params);//获取用户信息
let getUserInfo = (params = {}) => vm.$u.get('/system/user/info/', params); //获取用户信息
let getCode = (data = {}) => vm.$u.post('/auth/sms_code/', data); //获取短信验证码
let codeLogin = (data = {}) => vm.$u.post('/auth/login_sms_code/', data); //短信验证码登录
let login = (data = {}) => vm.$u.post('auth/token/', data); //账户密码登录
let loginOut = () => vm.$u.post('/auth/logout/'); //账户密码退出
// 将各个定义的接口名称统一放进对象挂载到vm.$u.api(因为vm就是this也即this.$u.api)下
let wxmplogin = (data = {}) => vm.$u.post('auth/login_wxmp/', data); //微信登录
let bindmp = (data = {}) => vm.$u.post('/system/user/bind_wxmp/', data); //微信小程序绑定
let unbindmp = (data = {}) => vm.$u.post('/system/user/unbind_wxmp/', data); //微信小程序解绑
let getDickey = (params={})=>vm.$u.get('/system/dict/', params);//查询字典
let userList = (params={})=>vm.$u.get('/system/user/', params);//
let deptList = (params={})=>vm.$u.get('/system/dept/', params);//
let getTickets = (params={})=>vm.$u.get('/wf/ticket/', params);//工单查询/wf/ticket/{id}/
let getTicketItem = (id)=>vm.$u.get(`/wf/ticket/${id}/`);//工单详情
let getTicketTransitions = (id)=>vm.$u.get(`/wf/ticket/${id}/transitions/`);//工单按钮查询
let addNode = (id,data={})=>vm.$u.get(`/wf/ticket/${id}/add_node/`,data);//加签
let addNodeEnd = (id,data={})=>vm.$u.get(`/wf/ticket/${id}/add_node_end/`,data);//加签处理
let deliver = (id,data={})=>vm.$u.get(`/wf/ticket/${id}/deliver/`,data);//转交工单
let ticketHandle = (id,data={})=>vm.$u.get(`/wf/ticket/${id}/handle/`,data);//工单处理
let operationCreat = (data = {}) => vm.$u.post('/opm/operation/', data);//作业
let operationItem = (id) => vm.$u.get(`/opm/operation/${id}/`);//作业许可证类型
let getOpreation = (id)=>vm.$u.get(`/opm/operation/${id}/`);//rpj查询
let getOpl = (id)=>vm.$u.get(`/opm/opl/${id}/`);//opl作业许可证查询
let oplLists = (data = {}) => vm.$u.get('/opm/opl/', data);//作业许可证
let oplCate = (data = {}) => vm.$u.get('/opm/opl_cate/', data);//作业许可证类型
let oplCateItem = (id) => vm.$u.get(`/opm/opl_cate/${id}/`);//作业许可证类型详情
let areaLists = (data = {}) => vm.$u.get('/am/area/', data);//作业区域
let getVisit = (id)=>vm.$u.get(`/vm/visit/${id}/`);//visit查询
let vmVisitor = (data={})=>vm.$u.get(`/vm/visitor/`,data);//visit查询
let addVisitor = (data={})=>vm.$u.post(`vm/visitor/`,data);//visitor添加
let getRpj = (id)=>vm.$u.get(`/rpm/rpj/${id}`);//rpj查询
let wxmplogin = (data = {}) => vm.$u.post('auth/login_wxmp/', data); //微信登录
let bindmp = (data = {}) => vm.$u.post('/system/user/bind_wxmp/', data); //微信小程序绑定
let unbindmp = (data = {}) => vm.$u.post('/system/user/unbind_wxmp/', data); //微信小程序解绑
let getDickey = (params = {}) => vm.$u.get('/system/dict/', params); //查询字典
let userList = (params = {}) => vm.$u.get('/system/user/', params); //
let deptList = (params = {}) => vm.$u.get('/system/dept/', params); //
vm.$u.api = {getUserInfo,
getCode,
codeLogin,
login,
loginOut,
wxmplogin,
bindmp,
unbindmp,
userList,
deptList,
getDickey,
getTickets,
getTicketItem,
getTicketTransitions,
getVisit,
vmVisitor,
addVisitor,
getRpj,
getOpreation,
oplCateItem,
oplLists,
getOpl,
oplCate,
operationItem,
operationCreat,
areaLists
};
let getTickets = (params = {}) => vm.$u.get('/wf/ticket/', params); //工单查询/wf/ticket/{id}/
let ticketCreate = (data = {}) => vm.$u.post('/wf/ticket/', data); //工单
let getTicketItem = (id) => vm.$u.get(`/wf/ticket/${id}/`); //工单详情
let getTicketTransitions = (id) => vm.$u.get(`/wf/ticket/${id}/transitions/`); //工单按钮查询
let workflowInit = (key) => vm.$u.get(`/wf/workflow/${key}/init_key/`); //工单按钮查询
let addNode = (id, data = {}) => vm.$u.get(`/wf/ticket/${id}/add_node/`, data); //加签
let addNodeEnd = (id, data = {}) => vm.$u.get(`/wf/ticket/${id}/add_node_end/`, data); //加签处理
let deliver = (id, data = {}) => vm.$u.get(`/wf/ticket/${id}/deliver/`, data); //转交工单
let ticketHandle = (id, data = {}) => vm.$u.post(`/wf/ticket/${id}/handle/`, data); //工单处理
let operationList = (data = {}) => vm.$u.get('/opm/operation/', data); //作业列表
let operationItem = (id) => vm.$u.get(`/opm/operation/${id}/`); //作业详情
let operationCreat = (data = {}) => vm.$u.post('/opm/operation/', data); //作业新建
let operationUpdate = (id, data = {}) => vm.$u.get(`/opm/operation/${id}/`, data); //作业编辑
let oplItem = (id) => vm.$u.get(`/opm/opl/${id}/`); //opl作业许可证查询
let oplLists = (data = {}) => vm.$u.get('/opm/opl/', data); //作业许可证
let oplCate = (data = {}) => vm.$u.get('/opm/opl_cate/', data); //作业许可证类型
let oplCateItem = (id) => vm.$u.get(`/opm/opl_cate/${id}/`); //作业许可证类型详情
let rpjList = (data = {}) => vm.$u.get(`/rpm/rpj/`, data); //rpj查询
let rpjItem = (id) => vm.$u.get(`/rpm/rpj/${id}`); //rpj查询
let areaLists = (data = {}) => vm.$u.get('/am/area/', data); //作业区域
let visitList = (data = {}) => vm.$u.get(`/vm/visit/`, data); //来访项目查询
let visitItem = (id) => vm.$u.get(`/vm/visit/${id}/`); //来访项目详情
let visitCreate = (data = {}) => vm.$u.post(`/vm/visit/`, data); //新增来访项目
let visitUpdate = (id, data = {}) => vm.$u.put(`/vm/visit/${id}/`, data); //编辑来访项目
let vmVisitor = (data = {}) => vm.$u.get(`/vm/visitor/`, data); //来访人员列表
let visitorCreate = (data = {}) => vm.$u.post(`vm/visitor/`, data); //来访人员添加
let visitorUpdate = (data = {}) => vm.$u.put(`vm/visitor/${id}/`, data); //来访人员编辑
let vmVpeople = (data = {}) => vm.$u.get(`/vm/vpeople/`, data); //来访人员列表
let vpeopleCreate = (data = {}) => vm.$u.post(`vm/vpeople/`, data); //来访人员添加
let vpeopleUpdate = (data = {}) => vm.$u.put(`vm/vpeople/${id}/`, data); //来访人员编辑
vm.$u.api = {
getUserInfo,
getCode,
codeLogin,
login,
loginOut,
wxmplogin,
bindmp,
unbindmp,
userList,
deptList,
ticketCreate,
getDickey,
getTickets,
getTicketItem,
workflowInit,
getTicketTransitions,
visitList,
visitItem,
visitCreate,
visitUpdate,
vmVisitor,
visitorCreate,
visitorUpdate,
vmVpeople,
vpeopleCreate,
vpeopleUpdate,
rpjItem,
rpjList,
oplCateItem,
operationItem,
operationCreat,
operationList,
oplLists,
oplItem,
oplCate,
areaLists
};
}
export default {
install
}
}

View File

@ -92,29 +92,22 @@
}
},
{
"path": "pages/workSpace/newWork/work",
"path": "pages/workSpace/rpj/rpjLisst",
"style": {
"navigationBarTitleText": "新建作业",
"navigationBarTitleText": "入厂项目",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/newWork/relevant",
"path": "pages/workSpace/rpj/rpjCreate",
"style": {
"navigationBarTitleText": "新建入厂项目",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/newWork/visit",
"style": {
"navigationBarTitleText": "新建来访项目",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/newWork/userList",
"style": {
@ -132,7 +125,7 @@
}
},
{
"path": "pages/workSpace/list/opreation",
"path": "pages/workSpace/operation/operationList",
"style": {
"navigationBarTitleText": "作业列表",
"navigationStyle": "custom",
@ -140,7 +133,15 @@
}
},
{
"path": "pages/workSpace/list/oplCate",
"path": "pages/workSpace/operation/operationCreate",
"style": {
"navigationBarTitleText": "新建作业",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/operation/oplCate",
"style": {
"navigationBarTitleText": "许可证类型",
"navigationStyle": "custom",
@ -148,17 +149,17 @@
}
},
{
"path": "pages/workSpace/list/rpj",
"path": "pages/workSpace/visit/visitList",
"style": {
"navigationBarTitleText": "入厂项目",
"navigationBarTitleText": "来访项目",
"navigationStyle": "custom",
"enablePullDownRefresh": false
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/list/visit",
"path": "pages/workSpace/visit/visitCreate",
"style": {
"navigationBarTitleText": "来访项目",
"navigationBarTitleText": "新建来访项目",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
@ -171,6 +172,14 @@
"enablePullDownRefresh": false
}
},
{
"path": "pages/workSpace/visit/vpeopleList",
"style": {
"navigationBarTitleText": "人员确定",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/my/my",
"style": {

View File

@ -31,7 +31,7 @@
</view>
</view>
<view class="btn">
<button type="default" class="save-btn" @click="saveUser">保存</button>
<button type="default" class="save-btn" @click="saveVisitor">保存</button>
</view>
</view>
</template>
@ -50,11 +50,11 @@
},
methods: {
saveUser(){
this.$u.api.addVisitor(this.formData).then(res=>{
saveVisitor(){
this.$u.api.visitorCreate(this.formData).then(res=>{
if(res.err_msg){}else{
uni.navigateTo({
url: '/pages/workSpace/newWork/userList'
url: '/pages/workSpace/visit/vpeopleList'
})
}
})

View File

@ -15,30 +15,43 @@
</view>
</label>
</checkbox-group>
<!-- <view class="row" v-for="(row,index) in userRange" :key="index" @tap="select(row)">
<view class="row" v-for="(row,index) in userRange" :key="index" @tap="select(row)">
<view class="center">
<view class="name-tel">
<view class="name">姓名{{row.name}}</view>
<view class="tel">手机号{{row.phone}}</view>
<view class="tel">身份证号{{row.id_number}}</view>
</view>
<view class="photo">
{{row.photo}}
</view>
</view>
<view class="right">
<view class="icon bianji" @tap.stop="edit(row)">
</view>
</view>
</view>
-->
</view>
<view class="add">
<view class="btn">
<button type="primary" class="save-btn" @click="add">新增人员</button>
<button type="primary" class="select">选择人员</button>
<view style="position: fixed;width: 100vw;height: 100vh;background-color: rgba(0,0,0,.3);top: 0;left: 0;z-index: 101;">
<view style="width: 80vw;position: absolute;top: 50%;margin: auto;background-color: #ffffff;left: 10vw;transform: translateY(-50%);">
<view>选择来访人员</view>
<form @submit="formSubmit">
<view class="uni-form-item uni-column">
<view class="title">访客</view>
<uni-data-select :localdata="userRange">
</uni-data-select>
</view>
<view class="uni-form-item uni-column">
<view class="title">是否主访客</view>
<view>
<switch name="switch" />
</view>
</view>
<view class="uni-btn-v">
<button class="mini-btn" type="primary" size="mini" form-type="submit">确定</button>
</view>
</form>
</view>
</view>
</view>
<button type="primary" class="add" @click="add">新增人员</button>
</view>
</template>
@ -81,13 +94,13 @@
page: 0
}).then(res => {
that.userRange = [];
res.forEach(item=>{
res.forEach(item => {
let obj = {};
obj=item;
obj.checked = false;
obj = item;
obj.checked = false;
that.userRange.push(obj)
})
})
},
select(row) {},
@ -143,18 +156,24 @@
}
.add {
width: 50px;
height: 50px;
border-radius: 25px;
line-height: 50px;
box-shadow: 0 0 6px 2px rgba(0, 0, 0, .3);
z-index: 100;
position: fixed;
bottom: 0;
width: 100%;
height: 120upx;
justify-content: center;
align-items: center;
bottom: 100px;
right: 20px;
}
.btn {
.select {
margin: auto;
box-shadow: 0upx 5upx 10upx rgba(0, 0, 0, 0.4);
width: 70%;
width: 400rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
}
.save-btn {

View File

@ -1,16 +1,16 @@
<template>
<view class="qingjia-apply">
<view class="operation-body">
<uni-nav-bar @clickLeft="goBack()" class="nav-bar" height="110rpx" leftWidth="200rpx" leftText="作业信息"
leftIcon="left" border backgroundColor="#2cade8" color="#fff" fixed statusBar shadow></uni-nav-bar>
<view class="apply-info">
<view class="form-info">
<view class="form-left-text">
<text class="star">*</text>
<text>作业简介</text>
</view>
<textarea class="apply-reason-text" v-model="formData.name" maxlength="250" placeholder="请输入" />
</view>
<view class="apply-info">
<view class="form-info">
<view class="form-content ">
<view class="form-item border-bottom">
<view class="form-left">
@ -99,9 +99,8 @@
</uni-data-picker>
</view>
</view>
<view class="btn">
<button type="default" class="save-btn" @click="saveSubmit">下一步</button>
<view class="btn" v-if="showBtns">
<button type="primary" class="save-btn" @click="saveSubmit">下一步</button>
</view>
</view>
</view>
@ -112,7 +111,7 @@
var that;
var promise;
export default {
name: "work",
name: "operation",
data() {
const currentDate = this.getDate({
format: true
@ -135,24 +134,8 @@
publishRangeCon: '',
menuId: "",
itemId: "",
detail: false,
principal: {},
pkId: '',
isDisabled: false,
btnShow: true,
lsId: "",
sta: null,
eventStatus: "",
execId: '',
// 2022320
result: [],
//
imgFlag: false,
//
downFiles: {},
timeShow: false,
showBtns: false,
//
releaseWeb: [],
createTimeFromShow: false,
@ -188,7 +171,18 @@
}
},
onLoad(params) {
if(params.operationId){
this.operationId = params.operationId;
this.type = params.type;
this.getOperation();
if(params.type==='edit'){
this.showBtns = true;
}else{
this.showBtns = false;
}
}else{
this.showBtns = true;
}
},
onShow() {
this.getdept();
@ -197,12 +191,21 @@
this.range = [];
},
methods: {
//operation
getOperation() {
let that = this;
that.$u.api.operationItem(that.operationId).then((res) => {
that.formData.start_time = res.start_time; //
that.formData.end_time = res.end_time; //
that.operationName = res.name; //
console.log(res);
});
},
saveSubmit() {
console.log(this.formData)
this.formData.start_time = new Date(this.formData.start_time).toISOString();
this.formData.end_time = new Date(this.formData.end_time).toISOString();
this.$u.api.operationCreat(this.formData).then(res => {
debugger;
let params = `?operationId=${res.id}`;
uni.navigateTo({
url: '/pages/workSpace/list/oplCate'+params
@ -320,18 +323,7 @@
console.log(arr);
return arr;
},
onSubmit(type) {
if (!this.paramsCheck()) return;
if (this.detail && !this.formData.id) {
uni.showToast({
title: '缺少pkid',
icon: "none"
})
return;
}
this._updatePrintList(this.formData, type);
},
/* 参数验证 */
paramsCheck() {
var typeArr = [];
@ -440,138 +432,24 @@
return true;
},
/* 保存数据 */
_updatePrintList(data, type) {
this.formData.createTimeTo = this.formData.createTimeTo + ' ' + '00:00:00'
this.isDisabled = true;
let method = "post";
if (this.detail) {
/* 是详情页就使用put请求申请人自回显处得到。否则为新增页申请人为当前登录人*/
if (this.eventStatus == 4) { //
method = "put";
} else {
method = "post";
const newData = JSON.parse(JSON.stringify(data))
delete newData.newsBulletinId;
data = newData;
}
} else {
this.formData.itemInfo.applicant = this.userId;
}
bulletinNew(method, data).then(res => {
if (res.statusCode === 200) {
this.itemId = res.data.data.itemId;
if (type.indexOf("提交") > -1) {
this.$refs.submitApproval.submitApproval(this.itemId); /* 创建审批数据 */
} else {
/* 临时保存,不需要审批的数据,直接跳转*/
uni.showToast({
title: '保存成功',
icon: 'none',
duration: 2000,
success() {
setTimeout(function() {
this.isDisabled = false;
uni.navigateBack({
delta: 1
})
}, 2000)
}
})
}
} else {
this.formData.createTimeTo = this.formData.createTimeTo.substring(0, 10);
uni.showToast({
title: res.data.message,
icon: 'none'
})
}
}).catch(err => {
this.formData.createTimeTo = this.formData.createTimeTo.substring(0, 10);
uni.showToast({
title: '网络异常, 请求失败',
icon: 'none'
})
})
},
publishChange(e) {
var i = e.detail.value;
that.publishRangeCon = that.publishRange[i].name;
that.formData.scopeOfPublication = that.publishRange[i].id;
},
goBack() {
uni.navigateBack({
delta: 1
uni.navigateTo({
url: '/pages/workSpace/visit/visitList'
})
},
/* 获取部门列表 */
_getDeptListMenu() {
getDeptListMenu().then(res => {
if (res.statusCode === 200) {
let list = res.data.data;
this.depRange = list;
// 2022320
this.result = [];
if (list !== undefined && list !== null && list !== "" && Array.isArray(list) && list
.length > 0) {
this.result = flatten(list);
}
} else {
if (res.data.message == "token无效") return;
uni.showToast({
title: res.data.message,
icon: 'none'
})
}
}).catch(err => {
uni.showToast({
title: '网络异常, 请求失败',
icon: 'none'
})
})
},
onPopupclosed() {
if (this.lsId) {
this.formData.itemInfo.applicationDept = this.lsId;
}
},
onNodeClick(e) {
if (e.id !== undefined && e.id !== null && e.id !== "") {
this.lsId = e.id;
// 2022320
const currObj = this.result.find((item) => {
return item.id == this.lsId
});
if (currObj !== undefined && currObj !== null && currObj !== "") {
console.log(currObj);
if (currObj.children === null || currObj.children === undefined || currObj.children === "") {
this.formData.itemInfo.applicationDept = this.lsId;
}
}
}
},
/* 选择部门后得到最后部门名称 */
onchange(e) {
const value = e.detail.value;
let lastDepName = "";
if (value.length > 0) {
lastDepName = value[value.length - 1].text;
}
this.subscribeDeptName = lastDepName || "";
},
depChange(e) {
const idx = e.detail.value;
this.selectedDep = this.depRange[idx].name;
@ -611,11 +489,11 @@
>>>.uni-status-bar {
background-image: linear-gradient(90deg, #164cc3 0%, #2c6fd9 100%), linear-gradient(#e60012, #e60012) !important;
}
.qingjia-apply {
.operation-body {
background-color: #f3fbff;
padding-bottom: 227rpx;
padding-bottom: 20rpx;
}
.qingjia-apply>>>uni-input {
.operation-body>>>uni-input {
/* height: 100%; */
font-size: 30rpx;
}
@ -624,8 +502,8 @@
font-size: 32rpx !important;
}
.apply-info {
width: 720rpx;
.form-info {
width: 710rpx;
margin: 0 auto;
background-color: #FFFFFF;
border-radius: 10rpx;

View File

@ -15,21 +15,28 @@
</view>
<view class="empty-view"></view>
<view class="content">
<view class="item-wrap" v-for="(val,index) in ticketList" :key="val.id">
<view class="item-wrap" v-for="(val,index) in lists" :key="val.id">
<view class="duty-item">
<view class="top-info">
<view class="info-title">{{val.title}}</view>
<view class="info-title">{{val.name}}</view>
</view>
<view class="center-info">
<view class="info-details">所属工作流{{val.workflow_.name}}</view>
<view class="info-details">工单状态{{val.state_.name}}</view>
<view class="info-details">提交时间{{val.create_time}} </view>
<view class="info-details">作业状态{{stateOptions[val.state]}}</view>
<view class="info-details">生产状态{{val.state_work}}</view>
<view class="info-details">作业区域{{val.area_.name}} </view>
<view class="info-details">更新时间{{val.update_time}} </view>
<view class="info-details">属地部门{{val.dept_ter_.name}} </view>
<view class="info-details">业务部门{{val.dept_bus_.name}} </view>
<view class="info-details">创建人{{val.create_by_.name}} </view>
</view>
<view class="bottom-btns">
<view class="shenhezhong shenhe-status" @click="ticketHandle(val)">
<view class="shenhezhong shenhe-status" @click="operationHandle(val,'edit')" v-if="val.state===10">
<image src="../../../static/my/my_apply/blue-time.png" mode=""></image>
处理
编辑
</view>
<view class="shenhezhong shenhe-status" @click="operationHandle(val,'show')" v-else style="color: #15a306;">
<image src="../../../static/my/my_apply/tongguo.png" mode=""></image>
查看
</view>
</view>
</view>
@ -47,7 +54,14 @@
pageSize: 10,
pageNum: 1,
totalNum: 0,
ticketList: [],
lists: [],
stateOptions: {
10: "创建中",
20: "审批中",
30: "待作业",
40: "作业中",
50: "已关闭",
},
}
},
//
@ -64,44 +78,34 @@
}
},
onShow() {
this.ticketList = [];
// this.getTicketLists();
this.lists = [];
this.getLists();
},
//
onPullDownRefresh() {
this.pageNum = 1;
this.ticketList = [];
// this.getTicketLists();
this.getLists();
},
methods: {
getTicketLists() {
getLists() {
let that = this;
let obj = {};
obj.category = 'duty';
obj.pageNum = this.pageNum;
obj.pageSize = this.pageSize;
if (that.search !== '') {
obj.search = that.search;
}
obj.pageSize = this.pageSize;
that.$u.api.getTickets(obj).then(res => {
that.ticketList = that.ticketList.concat(res.results);
that.$u.api.operationList(obj).then(res => {
that.lists = that.lists.concat(res.results);
this.totalNum = res.count;
})
},
ticketHandle(val) {
let projectId = '',//Id
operation = null;//id
let catetype = val.workflow_.key;
if (catetype === 'visit') {
projectId = val.ticket_data.visit;
} else if (catetype === 'Fire') {
projectId = val.ticket_data.opl;
operation = val.ticket_data.operation ? val.ticket_data.operation : null;
}
const params = `?ticketId=${val.id}&projectId=${projectId}&cateType=${catetype}&operation=${operation}`;
operationHandle(val,type) {
let operation = val.id;//id
const params = `?operationId=${val.id}&type=${type}`;
uni.navigateTo({
url: '../detail/ticketHandle' + params,
url: '/pages/workSpace/operation/operationCreate' + params,
})
},
goBack() {
@ -111,14 +115,14 @@
},
searchHandle() {
this.pageNum = 1;
this.ticketList = [];
this.getTicketLists()
this.lists = [];
this.getLists()
},
resetSearch() {
this.pageNum = 1;
this.search = "";
this.ticketList = [];
this.getTicketLists();
this.lists = [];
this.getLists();
},
}
}
@ -216,10 +220,11 @@
}
.search-wrap {
background-blend-mode: normal,
normal;
background-blend-mode: normal,normal;
padding-bottom: 44rpx;
padding-top: 20rpx;
box-sizing: border-box;
background: #f3fbff;
}
.search-body {

View File

@ -1,6 +1,6 @@
<template>
<view class="qingjia-apply">
<uni-nav-bar @clickLeft="goBack()" class="nav-bar" height="110rpx" leftWidth="200rpx" leftText="入厂项目"
<uni-nav-bar @clickLeft="goBack()" class="nav-bar" height="110rpx" leftWidth="200rpx" leftText="来访项目"
leftIcon="left" border backgroundColor="#2cade8" color="#fff" fixed statusBar shadow></uni-nav-bar>
<view class="apply-info">
<view class="form-content ">
@ -25,7 +25,6 @@
</view>
<view class="form-item border-bottom" style="height: 300rpx;">
<view class="form-left">
<text class="star">*</text>
<text class="form-left-text">来访详述</text>
</view>
<view class="form-right">
@ -40,9 +39,10 @@
<text class="form-left-text">来访时间</text>
</view>
<view class="form-right form-date">
<picker mode="date" :value="formData.visit_time" @change="bindStartDateChange">
<uni-datetime-picker v-model="formData.visit_time" :border="false" />
<!-- <picker mode="date" :value="formData.visit_time" @change="bindStartDateChange">
<view class="uni-input">{{formData.visit_time}}</view>
</picker>
</picker> -->
</view>
</view>
<view class="form-item border-bottom">
@ -51,9 +51,10 @@
<text class="form-left-text">离开时间</text>
</view>
<view class="form-right form-date">
<picker mode="date" :value="formData.leave_time" @change="bindEndDateChange">
<uni-datetime-picker v-model="formData.leave_time" :border="false" />
<!-- <picker mode="date" :value="formData.leave_time" @change="bindEndDateChange">
<view class="uni-input">{{formData.leave_time}}</view>
</picker>
</picker> -->
</view>
</view>
<view class="form-item border-bottom">
@ -68,7 +69,6 @@
</view>
<view class="form-item border-bottom">
<view class="form-left">
<text class="star">*</text>
<text class="form-left-text">来访单位</text>
</view>
<view class="form-right">
@ -94,8 +94,8 @@
<input type="number" v-model="formData.count_people" maxlength="50" placeholder="来访人数(整数)" />
</view>
</view>
<view class="btn">
<button type="primary" class="save-btn" @click="nextHandle">下一步</button>
<view class="btn" v-if="showBtns">
<button type="primary" class="save-btn" @click="nextHandle">下一步</button>
</view>
</view>
</view>
@ -103,23 +103,17 @@
</template>
<script>
/* 这是条件编译,意思是只在APP中出现如下的代码小程序是不支持的 */
var that;
var promise;
import nonNullCheck from '../../../utils/nonNullCheck.js';
export default {
name: "visit",
data() {
const currentDate = this.getDate({
format: true
})
return {
date: currentDate,
formData: {
name: '', //访
purpose: '', //访
receptionist: '', //
visit_time: currentDate, //访
leave_time: currentDate, //
visit_time: '', //访
leave_time: '', //
description: '', //访
company: '', //访
level: '', //访
@ -131,26 +125,10 @@
menuId: "",
itemId: "",
detail: false,
principal: {},
pkId: '',
isDisabled: false,
btnShow: true,
lsId: "",
sta: null,
eventStatus: "",
execId: '',
// 2022320
result: [],
//
imgFlag: false,
//
downFiles: {},
timeShow: false,
//
releaseWeb: [],
createTimeFromShow: false,
createTimeFromList: [],
createTimeFromCon: '',
showBtns:false,
visitItem: {},
type: '',
visitId: '',
range: [{
text: "参观",
value: 10
@ -171,29 +149,41 @@
text: "重要",
value: 20
}],
userRange:[],
userRange: [],
}
},
computed: {
startDate() {
return this.getDate('start');
},
endDate() {
return this.getDate('end');
onLoad(params) {
debugger;
console.log(params)
if (params.visit) {
this.visitId = params.visit;
this.type = params.type;
this.getVisitItem();
if(this.type === 'show'){
this.showBtns = false;
}else{
this.showBtns = true;
}
} else {
this.showBtns = true;
}
},
onShow() {
this.getUserRange();
},
methods: {
//
getUserRange() {
this.$u.api.userList({page: 0}).then(res => {
this.$u.api.userList({
page: 0
}).then(res => {
let user = [];
let obj = {};
res.forEach(item => {
obj = {value: null,text: ''};
obj = {
value: null,
text: ''
};
obj.value = item.id;
obj.text = item.name;
user.push(obj);
@ -201,6 +191,11 @@
this.userRange = user
})
},
getVisitItem() {
this.$u.api.visitItem(this.visitId).then(res => {
this.formData = res;
})
},
getDate(type) {
const date = new Date();
let year = date.getFullYear();
@ -222,164 +217,101 @@
bindEndDateChange: function(e) {
this.formData.end_time = e.detail.value
},
happenTimeFun(num) { //
let date = new Date(num);
//10*1000131000
let y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? ('0' + MM) : MM; //0
let d = date.getDate();
d = d < 10 ? ('0' + d) : d; //0
let h = date.getHours();
h = h < 10 ? ('0' + h) : h; //0
let m = date.getMinutes();
m = m < 10 ? ('0' + m) : m; //0
let s = date.getSeconds();
s = s < 10 ? ('0' + s) : s; //0
//         return y + '-' + MM + '-' + d + ' ' + h + ':' + m+ ':' + s;
return y + '-' + MM + '-' + d;
},
createTimeToFn(e) {
that.formData.createTimeTo = e.year + '-' + e.month + '-' + e.day;
},
createTimeFromYesFn(e) {
console.log(e)
var index = e[0]
that.formData.createTimeFrom = that.createTimeFromList[index].id
that.createTimeFromCon = that.createTimeFromList[index].label
},
nextHandle(type) {
if (!this.paramsCheck()) return;
if (this.detail && !this.formData.id) {
uni.showToast({
title: '缺少pkid',
icon: "none"
})
let that = this;
if (!that.paramsCheck()) {
return;
} else {
debugger;
if (that.formData.id) {
that.formData.visit_time = new Date(that.formData.visit_time).toISOString();
that.formData.leave_time = new Date(that.formData.leave_time).toISOString();
that.$u.api.visitUpdate(that.formData.id, that.formData).then(res => {
if (res.err_msg) {
} else {
let params = `?visit=${that.formData.id}`;
uni.navigateTo({
url: '/pages/workSpace/visit/vpeopleList'+params
})
}
})
} else {
that.formData.visit_time = new Date(that.formData.visit_time).toISOString();
that.formData.leave_time = new Date(that.formData.leave_time).toISOString();
that.$u.api.visitCreate(that.formData).then(res => {
if (res.err_msg) {
} else {
uni.navigateTo({
url: '/pages/workSpace/visit/vpeopleList'
})
}
})
}
}
this._updatePrintList(this.formData, type);
},
/* 参数验证 */
paramsCheck() {
var typeArr = [];
for (let i = 0; i < that.releaseWeb.length; i++) {
if (that.releaseWeb[i].checked == true) {
typeArr.push(that.releaseWeb[i].id)
}
}
that.formData.typeList = typeArr;
if (!nonNullCheck(this.formData.itemInfo.itemName)) {
if (!nonNullCheck(this.formData.purpose)) {
uni.showToast({
title: '请输入标题',
title: '请输入来访事由',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.itemInfo.applicationDept)) {
if (!nonNullCheck(this.formData.name)) {
uni.showToast({
title: '请选择申请部门',
title: '请输入来访概述',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.createTimeTo)) {
if (!nonNullCheck(this.formData.visit_time)) {
uni.showToast({
title: '请选择申请日期',
title: '请选择来访时间',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.writer)) {
if (!nonNullCheck(this.formData.leave_time)) {
uni.showToast({
title: '请填写撰稿人',
title: '请选择离开时间',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.mailbox)) {
if (!nonNullCheck(this.formData.receptionist)) {
uni.showToast({
title: '请填写联系邮箱',
title: '请选择接待人人',
icon: "none"
})
return false;
}
if (emailRegular.test(this.formData.mailbox) === false) {
if (!nonNullCheck(this.formData.level)) {
uni.showToast({
title: '联系邮箱格式不对,请重新填写',
title: '请选择访问级别',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.contactNumber)) {
if (!nonNullCheck(this.formData.count_people)) {
uni.showToast({
title: '请填写联系电话',
title: '请填写来访人数',
icon: "none"
})
return false;
}
if (phoneRegular.test(this.formData.contactNumber) === false) {
uni.showToast({
title: '联系电话格式不对,请重新填写',
icon: "none"
})
return false;
}
if (that.formData.typeList.length == 0) {
uni.showToast({
title: '请选择发布网站',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.createTimeFrom)) {
uni.showToast({
title: '请选择信息有效期',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.releaseColumn)) {
uni.showToast({
title: '请填写发布栏目',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.newsInformation)) {
uni.showToast({
title: '请填写新闻信息',
icon: "none"
})
return false;
}
if (!nonNullCheck(this.formData.reason)) {
uni.showToast({
title: '请填写申请理由',
icon: "none"
})
return false;
}
return true;
},
goBack() {
uni.navigateBack({
delta: 1
})
},
nextHandle(){
uni.navigateTo({
url: '/pages/workSpace/newWork/userList'
})
},
}
}
</script>

View File

@ -15,21 +15,28 @@
</view>
<view class="empty-view"></view>
<view class="content">
<view class="item-wrap" v-for="(val,index) in ticketList" :key="val.id">
<view class="item-wrap" v-for="(val,index) in lists" :key="val.id">
<view class="duty-item">
<view class="top-info">
<view class="info-title">{{val.title}}</view>
<view class="info-title">{{val.name}}</view>
</view>
<view class="center-info">
<view class="info-details">所属工作流{{val.workflow_.name}}</view>
<view class="info-details">工单状态{{val.state_.name}}</view>
<view class="info-details">提交时间{{val.create_time}} </view>
<!-- <view class="info-details">作业状态{{stateOptions[val.state]}}</view> -->
<view class="info-details">来访概述{{val.description}}</view>
<!-- <view class="info-details">作业区域{{val.area_.name}} </view>
<view class="info-details">更新时间{{val.update_time}} </view>
<view class="info-details">属地部门{{val.dept_ter_.name}} </view>
<view class="info-details">业务部门{{val.dept_bus_.name}} </view>
<view class="info-details">创建人{{val.create_by_.name}} </view> -->
</view>
<view class="bottom-btns">
<view class="shenhezhong shenhe-status" @click="ticketHandle(val)">
<view class="shenhezhong shenhe-status" @click="visitHandle(val,'edit')" v-if="val.state===10">
<image src="../../../static/my/my_apply/blue-time.png" mode=""></image>
处理
编辑
</view>
<view class="shenhezhong shenhe-status" @click="visitHandle(val,'show')" v-else style="color: #15a306;">
<image src="../../../static/my/my_apply/tongguo.png" mode=""></image>
查看
</view>
</view>
</view>
@ -47,7 +54,14 @@
pageSize: 10,
pageNum: 1,
totalNum: 0,
ticketList: [],
lists: [],
stateOptions: {
10: "创建中",
20: "审批中",
30: "待作业",
40: "作业中",
50: "已关闭",
},
}
},
//
@ -55,7 +69,7 @@
const totalPage = Math.ceil(this.totalNum / this.pageSize);
if (this.pageNum < totalPage) {
this.pageNum += 1;
// this._getMyApplyList(false);
} else {
uni.showToast({
title: "已全部加载",
@ -64,44 +78,33 @@
}
},
onShow() {
this.ticketList = [];
// this.getTicketLists();
this.lists = [];
this.getLists();
},
//
onPullDownRefresh() {
this.pageNum = 1;
this.ticketList = [];
// this.getTicketLists();
this.getLists();
},
methods: {
getTicketLists() {
getLists() {
let that = this;
let obj = {};
obj.category = 'duty';
obj.pageNum = this.pageNum;
obj.pageSize = this.pageSize;
if (that.search !== '') {
obj.search = that.search;
}
obj.pageSize = this.pageSize;
that.$u.api.getTickets(obj).then(res => {
that.ticketList = that.ticketList.concat(res.results);
that.$u.api.visitList(obj).then(res => {
that.lists = that.lists.concat(res.results);
this.totalNum = res.count;
})
},
ticketHandle(val) {
let projectId = '',//Id
operation = null;//id
let catetype = val.workflow_.key;
if (catetype === 'visit') {
projectId = val.ticket_data.visit;
} else if (catetype === 'Fire') {
projectId = val.ticket_data.opl;
operation = val.ticket_data.operation ? val.ticket_data.operation : null;
}
const params = `?ticketId=${val.id}&projectId=${projectId}&cateType=${catetype}&operation=${operation}`;
visitHandle(val,type) {
const params = `?visit=${val.id}&type=${type}`;
uni.navigateTo({
url: '../detail/ticketHandle' + params,
url: '/pages/workSpace/visit/visitCreate' + params,
})
},
goBack() {
@ -111,14 +114,14 @@
},
searchHandle() {
this.pageNum = 1;
this.ticketList = [];
this.getTicketLists()
this.lists = [];
this.getLists()
},
resetSearch() {
this.pageNum = 1;
this.search = "";
this.ticketList = [];
this.getTicketLists();
this.lists = [];
this.getLists();
},
}
}
@ -216,10 +219,11 @@
}
.search-wrap {
background-blend-mode: normal,
normal;
background-blend-mode: normal,normal;
padding-bottom: 44rpx;
padding-top: 20rpx;
box-sizing: border-box;
background: #f3fbff;
}
.search-body {

View File

@ -0,0 +1,288 @@
<template>
<view class="list-body">
<uni-nav-bar @clickLeft="goBack()" class="nav-bar" height="110rpx" leftWidth="200rpx" leftText="人员选择"
leftIcon="left" border backgroundColor="#2cade8" color="#fff" fixed statusBar shadow></uni-nav-bar>
<view class="apply-info">
<view class="row" v-for="(row,index) in vpeopleList" :key="index" @tap="select(row)">
<view class="center">
<view class="name-tel">
<view class="name">姓名{{row.text}}</view>
<view class="tel">手机号{{row.visitor_.phone}}</view>
<view class="tel">身份证号{{row.visitor_.id_number}}</view>
</view>
</view>
<view class="right">
<view class="icon bianji" @tap.stop="edit(row)">
</view>
</view>
</view>
<button type="primary" class="select" @click="checkPeople">选择人员</button>
</view>
<button type="primary" class="addNew" @click="add">新增人员</button>
<view class="dialogWrap" v-if="limitedPeople">
<view class="dialogCont">
<view class="dialogTitle">
<view>选择来访人员</view>
<view class="dialogCloseImg" @click="closeDialog"></view>
</view>
<form @submit="formSubmit">
<view class="uni-form-item uni-column">
<view class="title">访客</view>
<uni-data-select name="visitor" :localdata="userRange" v-model="formData.visitor">
</uni-data-select>
</view>
<view class="uni-form-item uni-column">
<view class="title">是否主访客</view>
<view>
<switch name="is_main" v-model="formData.is_main" />
</view>
</view>
<view class="uni-btn-v">
<button class="mini-btn" type="primary" size="mini" form-type="submit">确定</button>
</view>
</form>
</view>
</view>
<view class="apply-info" style="min-height: fit-content;display: flex;">
<button v-for=" item in initform.transitions" :key="item.id" @click="submitticket(item.id)" type="primary" style="width: 25%;">{{item.name}}
</button>
<button type="warn" style="width: 25%;">退出</button>
</view>
</view>
</template>
<script>
export default {
name: "vpeopleList",
data() {
return {
limitedPeople: false,
formData: {
visit: '',
visitor: '',
is_main: true,
},
initform: {},
vpeopleList: [],
userRange: [],
}
},
onLoad(params) {
this.visitId = params.visit;
},
onShow() {
this.getUserRange();
this.getVpeopleList();
this.getInit();
},
methods: {
formSubmit(val) {
let that = this;
that.formData.visit = that.visitId;
that.$u.api.vpeopleCreate(that.formData).then(res => {
if (res.err_msg) {} else {
that.getVpeopleList();
this.limitedPeople = false;
}
})
},
//
getUserRange() {
let that = this;
that.$u.api.vmVisitor({
page: 0
}).then(res => {
that.userRange = [];
let user = [];
let obj = {};
res.forEach(item => {
obj = item;
obj.value = item.id;
obj.text = item.name;
user.push(obj);
})
that.userRange = user
})
},
//
getVpeopleList() {
let that = this;
that.$u.api.vmVpeople({
page: 0,
visit: '1554721956950052864'
}).then(res => {
that.vpeopleList = [];
let user = [];
let obj = {};
res.forEach(item => {
obj = item;
obj.value = item.id;
obj.text = item.visitor_.name;
user.push(obj);
})
that.vpeopleList = user
})
},
checkPeople() {
this.limitedPeople = true;
},
closeDialog() {
this.limitedPeople = false;
},
select(row) {},
goBack() {
uni.navigateBack({
delta: 1
})
},
add() {
uni.navigateTo({
url: '/pages/workSpace/newWork/addUser'
})
},
edit(row) {},
getInit() {
this.$u.api.workflowInit('visit').then((res) => {
this.initform = res;
});
},
//
submitticket(id) {
let ticket = {};
ticket.workflow = this.initform.workflow;
ticket.ticket_data = {
visit: this.visitId
};
ticket.transition = id;
this.$u.api.ticketCreate(ticket).then((res) => {
if(res.err_msg){}else{
uni.reLaunch({
url: '/pages/workSpace/workSpace'
})
}
});
}
}
}
</script>
<style>
>>>.uni-navbar__header,
>>>.uni-status-bar {
background-image: linear-gradient(90deg, #164cc3 0%, #2c6fd9 100%), linear-gradient(#e60012, #e60012) !important;
}
.list-body {
background-color: #f3fbff;
padding-bottom: 113px;
}
.apply-info {
min-height: 70vh;
width: 710upx;
margin: 0 auto;
background-color: #FFFFFF;
border-radius: 5px;
padding: 12px 16px;
box-sizing: border-box;
margin-top: 12px;
}
.row {
padding: 10upx;
margin-bottom: 20upx;
border-bottom: 1upx solid #eeeeee;
}
.uni-list-cell {
display: flex;
padding: 10upx;
margin-bottom: 20upx;
border-bottom: 1upx solid #eeeeee;
}
.addNew {
width: 50px;
height: 50px;
border-radius: 25px;
line-height: 50px;
box-shadow: 0 0 6px 2px rgba(0, 0, 0, .3);
z-index: 100;
position: fixed;
bottom: 20px;
right: 20px;
}
.select {
margin: auto;
box-shadow: 0upx 5upx 10upx rgba(0, 0, 0, 0.4);
width: 400rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
}
.save-btn {
height: 80rpx;
color: #fff;
font-size: 30upx;
justify-content: center;
align-items: center;
}
.dialogWrap {
position: fixed;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, .3);
top: 0;
left: 0;
z-index: 110;
}
.dialogCont {
width: 80vw;
position: absolute;
top: 50%;
margin: auto;
background-color: #ffffff;
left: 10vw;
transform: translateY(-50%);
padding: 20rpx;
border-radius: 20rpx;
}
.dialogTitle {
font-size: 36rpx;
padding-bottom: 20rpx;
border-bottom: 1px solid #eeeeee;
display: flex;
justify-content: space-between;
}
.uni-form-item {
height: 160rpx;
}
.uni-form-item>.title {
height: 80rpx;
line-height: 80rpx;
font-size: 32rpx;
}
.uni-btn-v {
text-align: center;
}
.dialogCloseImg {
width: 52rpx;
height: 52rpx;
background-image: url('../../../static/my/my_apply/zuofei.png');
background-repeat: no-repeat;
background-size: cover;
}
</style>

View File

@ -6,32 +6,16 @@
</view>
<view class="top-title" style="display: flex;">
<block v-for="(item,index) in routerList" :key="item.index">
<!-- <view class="title-item" v-if="item.children">
<view class="title-icon" >
<image :src="require('@/static/worSpace/'+item.icon+'')" mode="widthFix"></image>
</view>
<text class="title-text" >{{item.name}}</text>
<picker mode="selector" :range="item.childItems" @change="intoAddPage($event,item.childUrls)" range-key="name">
<view class="workbench-picker">
{{name}}
</view>
</picker>
</view> -->
<view class="title-item" @click="goInto(index)">
<view class="title-icon">
<image :src="require('@/static/workSpace/'+item.icon+'')" mode="widthFix"></image>
</view>
<text class="title-text">{{item.name}}</text>
</view>
</block>
</view>
</view>
<view style="height: 22rpx;">
</view>
<view class="my-apply">
<view class="title">
@ -45,31 +29,6 @@
</view>
</view>
<view class="line"></view>
<view class="apply-item" v-for="(val,index) in myApplyArray" :key="val.pkId" @click="intoUpdataPage(val)">
<view style="display: flex;">
<view class="apply-title">
{{val.itemName}}
</view>
<view class="apply-status" :style="{color: val.statusColor}">
{{val.eventStatusValue}}
</view>
<!-- <image src="../../static/logo.png" mode="" class="image"></image> -->
</view>
<view class="apply-content">
所属模块{{val.menuName}}
</view>
<view style="display: flex;">
<view class="apply-content">
申请人{{val.applicantName}}
</view>
<view class="apply-time">
{{val.submissionTime}}
</view>
</view>
</view>
</view>
<view class="my-apply">
@ -84,31 +43,6 @@
</view>
</view>
<view class="line"></view>
<view class="apply-item" v-for="(val,index) in myApplyArray" :key="val.pkId" @click="intoUpdataPage(val)">
<view style="display: flex;">
<view class="apply-title">
{{val.itemName}}
</view>
<view class="apply-status" :style="{color: val.statusColor}">
{{val.eventStatusValue}}
</view>
<!-- <image src="../../static/logo.png" mode="" class="image"></image> -->
</view>
<view class="apply-content">
所属模块{{val.menuName}}
</view>
<view style="display: flex;">
<view class="apply-content">
申请人{{val.applicantName}}
</view>
<view class="apply-time">
{{val.submissionTime}}
</view>
</view>
</view>
</view>
<view class="my-apply">
@ -123,31 +57,6 @@
</view>
</view>
<view class="line"></view>
<view class="apply-item" v-for="(val,index) in myApplyArray" :key="val.pkId" @click="intoUpdataPage(val)">
<view style="display: flex;">
<view class="apply-title">
{{val.itemName}}
</view>
<view class="apply-status" :style="{color: val.statusColor}">
{{val.eventStatusValue}}
</view>
<!-- <image src="../../static/logo.png" mode="" class="image"></image> -->
</view>
<view class="apply-content">
所属模块{{val.menuName}}
</view>
<view style="display: flex;">
<view class="apply-content">
申请人{{val.applicantName}}
</view>
<view class="apply-time">
{{val.submissionTime}}
</view>
</view>
</view>
</view>
</view>
@ -160,42 +69,17 @@
name: "",
username: "",
routerList: [{
name: '作业管理',
name: '新增作业',
icon: 'specialmatter.png',
path: 'index',
childItems: [{
name: "请假申请"
},
{
name: "公出申请"
},
{
name: "出差申请"
},
{
name: "值班申请"
},
{
name: "未打卡说明"
}
],
childUrls: [
"/pages/workSpace/new_apply/del",
"/pages/workSpace/new_apply/del",
"/pages/workSpace/new_apply/del",
"/pages/workSpace/new_apply/del",
"/pages/workSpace/new_apply/del",
]
},
{
name: '入厂项目',
name: '新增入厂',
icon: 'hetong.png',
path: 'index'
},
{
name: '来访项目',
name: '新增来访',
icon: 'renli.png',
path: 'index'
},
@ -212,15 +96,15 @@
goInto(index) {
if (index == 0) {
uni.navigateTo({
url: '/pages/workSpace/newWork/work'
url: '/pages/workSpace/operation/operationCreate'
})
} else if (index == 1) {
uni.navigateTo({
url: '/pages/workSpace/newWork/relevant'
url: '/pages/workSpace/rpj/rpjCreate'
})
} else if (index == 2) {
uni.navigateTo({
url: '/pages/workSpace/newWork/visit'
url: '/pages/workSpace/visit/visitCreate'
})
}
@ -269,233 +153,6 @@
})
},
initList(routes) {
const obj = routes.find(item => {
return item.path === '/apply'
})
//
const project = routes.find(item => {
return item.path === '/project_management'
})
//
const inform = routes.find(item => {
return item.path === '/press'
})
let projectObj;
let informObj;
if (project) { //
projectObj = project.children.find(item => {
return item.path == "hetongxinxi_shoukuan";
})
}
if (inform) { //
informObj = inform.children.find(item => {
return item.path == "index";
})
}
if (obj) {
const newObj = JSON.parse(JSON.stringify(obj));
let arr = newObj.children;
const index = arr.findIndex(item => {
return item.path == "index";
});
if (index !== -1) {
arr.splice(index, 1); // index
}
if (informObj) {
const newInformObj = JSON.parse(JSON.stringify(informObj));
arr.splice(arr.length, 0, newInformObj); //
}
let htBackItem;
for (let val of arr) {
if (val.path == "yewufeiyong") {
htBackItem = val;
break;
} else if (val.path == "jiesuanguanli") {
htBackItem = val;
break;
} else if (val.path == "index_detail_xinwen") {
htBackItem = val;
break;
} else if (val.path == "special_matter") {
htBackItem = val;
break;
} else if (val.path == "issue_report") {
htBackItem = val;
break;
} else if (val.path == "index") {
htBackItem = val;
break;
}
}
if (projectObj) {
const newProjectObj = JSON.parse(JSON.stringify(projectObj));
newProjectObj.name = "创建合同";
if (htBackItem) {
const backIndex = arr.findIndex(item => {
return item == htBackItem;
})
if (backIndex !== -1) {
arr.splice(backIndex, 0, newProjectObj); //
} else {
arr.push(newProjectObj) //
}
} else {
arr.push(newProjectObj)
}
}
this.routerList = arr.map(item => {
item.childItems = [];
item.childUrls = [];
item.icon = "kaoqin.png";
if (item.path == "kqgl") {
item.icon = "kaoqin.png";
item.childItems = [{
name: "请假申请"
},
{
name: "公出申请"
},
{
name: "出差申请"
},
{
name: "值班申请"
},
{
name: "未打卡说明"
}
];
item.childUrls = [
"/pages/workSpace/new_apply/kaoqin_management/qingjia_apply",
"/pages/workSpace/new_apply/kaoqin_management/gongchu_apply",
"/pages/workSpace/new_apply/kaoqin_management/chuchai_apply",
"/pages/workSpace/new_apply/kaoqin_management/zhiban_apply",
"/pages/workSpace/new_apply/kaoqin_management/weidaka_apply",
]
} else if (item.path == "cl") {
item.icon = "cheliang.png";
item.childItems = [{
name: "车辆维修、保养"
},
{
name: "私车公用申请"
},
{
name: "车辆使用登记"
},
];
item.childUrls = [
"/pages/workSpace/new_apply/car_management/repair_car_apply",
"/pages/workSpace/new_apply/car_management/private_car_public",
"/pages/workSpace/new_apply/car_management/paicheshenqing",
]
} else if (item.path == "cg") {
item.icon = "caigou.png";
item.childItems = [{
name: "印刷品清单"
},
{
name: "办公用品采购申请表"
},
{
name: "固定资产采购申请表"
},
{
name: "低值易耗品购置申请表"
}
];
item.childUrls = [
"/pages/workSpace/new_apply/caigou_management/print_list_apply",
"/pages/workSpace/new_apply/caigou_management/office_supplies_apply",
"/pages/workSpace/new_apply/caigou_management/fixed_assets_apply",
"/pages/workSpace/new_apply/caigou_management/low_value_products_apply"
];
} else if (item.path == "gdzc") {
item.icon = "fixedassets.png";
item.childItems = [{
name: "验收记录"
},
{
name: "内部调拨记录表"
},
{
name: "报废申请表"
},
{
name: "维修申请表"
}
];
item.childUrls = [
"/pages/workSpace/new_apply/fixed_assets_management/yanshoujilu",
"/pages/workSpace/new_apply/fixed_assets_management/neibu_diaobo_apply",
"/pages/workSpace/new_apply/fixed_assets_management/baofeishenqing",
"/pages/workSpace/new_apply/fixed_assets_management/weixiushenqing"
];
} else if (item.path == "jiesuanguanli") {
item.icon = "jiesuan.png";
} else if (item.path == "xinziguanli") {
item.icon = "xinzi.png";
} else if (item.path == "yewufeiyong") {
item.icon = "yewu.png";
} else if (item.path == "hetongxinxi_shoukuan") {
item.icon = "hetong.png";
} else if (item.path == "yzgl") {
item.icon = "yinzhang.png";
item.childItems = [{
name: "刻章申请表"
},
{
name: "重要文件/印鉴借用"
},
{
name: '销毁印鉴申请表'
},
{
name: "印章申请表"
}
];
item.childUrls = [
"/pages/workSpace/new_apply/yinzhang__management/kedushenqingbiao",
"/pages/workSpace/new_apply/yinzhang__management/zhongyaowenjian",
"/pages/workSpace/new_apply/yinzhang__management/xiaohuiyinjian",
"/pages/workSpace/new_apply/yinzhang__management/yinzhangshenqingbiao"
];
} else if (item.path == "zdwj") {
item.name = "制度文件";
item.icon = "zhidu.png";
item.childItems = [{
name: "红头文件审批"
},
{
name: "红头文件审批(涉及财务)"
},
];
item.childUrls = [
"/pages/workSpace/new_apply/zhiduwenjian_management/hongtouwenjian",
"/pages/workSpace/new_apply/zhiduwenjian_management/hongtouwenjian_cw"
];
} else if (item.path == "issue_report") {
item.icon = "fafang.png"
} else if (item.path == "special_matter") {
item.icon = "specialmatter.png"
} else if (item.path == "index") {
item.name = "通知公告";
item.icon = "tongzhigonggao.png"
}
return item;
})
}
},
/* 跳转详情页 */
intoUpdataPage(val) {
@ -582,15 +239,15 @@
goIntoMoreApply(index) {
if (index === 'operation')
uni.navigateTo({
url: '/pages/workSpace/list/opreation'
url: '/pages/workSpace/operation/operationList'
})
else if (index === 'rpj')
uni.navigateTo({
url: '/pages/workSpace/list/rpj'
url: '/pages/workSpace/rpj/rpjLisst'
})
else if (index === 'visit')
uni.navigateTo({
url: '/pages/workSpace/list/visit'
url: '/pages/workSpace/visit/visitList'
})
}
}

View File

@ -0,0 +1,26 @@
## 1.3.12021-12-20
- 修复 在vue页面下略缩图显示不正常的bug
## 1.3.02021-11-19
- 重构插槽的用法 header 替换为 title
- 新增 actions 插槽
- 新增 cover 封面图属性和插槽
- 新增 padding 内容默认内边距离
- 新增 margin 卡片默认外边距离
- 新增 spacing 卡片默认内边距
- 新增 shadow 卡片阴影属性
- 取消 mode 属性,可使用组合插槽代替
- 取消 note 属性 使用actions插槽代替
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card)
## 1.2.12021-07-30
- 优化 vue3下事件警告的问题
## 1.2.02021-07-13
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.82021-07-01
- 优化 图文卡片无图片加载时,提供占位图标
- 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持)
- 修复 thumbnail 不存在仍然占位的 bug
## 1.1.72021-05-12
- 新增 组件示例地址
## 1.1.62021-02-04
- 调整为uni_modules目录规范

View File

@ -0,0 +1,270 @@
<template>
<view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}"
:style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}">
<!-- 封面 -->
<slot name="cover">
<view v-if="cover" class="uni-card__cover">
<image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image>
</view>
</slot>
<slot name="title">
<view v-if="title || extra" class="uni-card__header">
<!-- 卡片标题 -->
<view class="uni-card__header-box" @click="onClick('title')">
<view v-if="thumbnail" class="uni-card__header-avatar">
<image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" />
</view>
<view class="uni-card__header-content">
<text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text>
<text v-if="title&&subTitle"
class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text>
</view>
</view>
<view class="uni-card__header-extra" @click="onClick('extra')">
<text class="uni-card__header-extra-text">{{ extra }}</text>
</view>
</view>
</slot>
<!-- 卡片内容 -->
<view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')">
<slot></slot>
</view>
<view class="uni-card__actions" @click="onClick('actions')">
<slot name="actions"></slot>
</view>
</view>
</template>
<script>
/**
* Card 卡片
* @description 卡片视图组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=22
* @property {String} title 标题文字
* @property {String} subTitle 副标题
* @property {Number} padding 内容内边距
* @property {Number} margin 卡片外边距
* @property {Number} spacing 卡片内边距
* @property {String} extra 标题额外信息
* @property {String} cover 封面图本地路径需要引入
* @property {String} thumbnail 标题左侧缩略图
* @property {Boolean} is-full = [true | false] 卡片内容是否通栏 true 时将去除padding值
* @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影
* @property {String} shadow 卡片阴影
* @property {Boolean} border 卡片边框
* @event {Function} click 点击 Card 触发事件
*/
export default {
name: 'UniCard',
emits: ['click'],
props: {
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
},
padding: {
type: String,
default: '10px'
},
margin: {
type: String,
default: '15px'
},
spacing: {
type: String,
default: '0 10px'
},
extra: {
type: String,
default: ''
},
cover: {
type: String,
default: ''
},
thumbnail: {
type: String,
default: ''
},
isFull: {
//
type: Boolean,
default: false
},
isShadow: {
//
type: Boolean,
default: true
},
shadow: {
type: String,
default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
},
border: {
type: Boolean,
default: true
}
},
methods: {
onClick(type) {
this.$emit('click', type)
}
}
}
</script>
<style lang="scss">
$uni-border-3: #EBEEF5 !default;
$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
$uni-main-color: #3a3a3a !default;
$uni-base-color: #6a6a6a !default;
$uni-secondary-color: #909399 !default;
$uni-spacing-sm: 8px !default;
$uni-border-color:$uni-border-3;
$uni-shadow: $uni-shadow-base;
$uni-card-title: 15px;
$uni-cart-title-color:$uni-main-color;
$uni-card-subtitle: 12px;
$uni-cart-subtitle-color:$uni-secondary-color;
$uni-card-spacing: 10px;
$uni-card-content-color: $uni-base-color;
.uni-card {
margin: $uni-card-spacing;
padding: 0 $uni-spacing-sm;
border-radius: 4px;
overflow: hidden;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
background-color: #fff;
flex: 1;
.uni-card__cover {
position: relative;
margin-top: $uni-card-spacing;
flex-direction: row;
overflow: hidden;
border-radius: 4px;
.uni-card__cover-image {
flex: 1;
// width: 100%;
/* #ifndef APP-PLUS */
vertical-align: middle;
/* #endif */
}
}
.uni-card__header {
display: flex;
border-bottom: 1px $uni-border-color solid;
flex-direction: row;
align-items: center;
padding: $uni-card-spacing;
overflow: hidden;
.uni-card__header-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
align-items: center;
overflow: hidden;
}
.uni-card__header-avatar {
width: 40px;
height: 40px;
overflow: hidden;
border-radius: 5px;
margin-right: $uni-card-spacing;
.uni-card__header-avatar-image {
flex: 1;
width: 40px;
height: 40px;
}
}
.uni-card__header-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
flex: 1;
// height: 40px;
overflow: hidden;
.uni-card__header-content-title {
font-size: $uni-card-title;
color: $uni-cart-title-color;
// line-height: 22px;
}
.uni-card__header-content-subtitle {
font-size: $uni-card-subtitle;
margin-top: 5px;
color: $uni-cart-subtitle-color;
}
}
.uni-card__header-extra {
line-height: 12px;
.uni-card__header-extra-text {
font-size: 12px;
color: $uni-cart-subtitle-color;
}
}
}
.uni-card__content {
padding: $uni-card-spacing;
font-size: 14px;
color: $uni-card-content-color;
line-height: 22px;
}
.uni-card__actions {
font-size: 12px;
}
}
.uni-card--border {
border: 1px solid $uni-border-color;
}
.uni-card--shadow {
position: relative;
/* #ifndef APP-NVUE */
box-shadow: $uni-shadow;
/* #endif */
}
.uni-card--full {
margin: 0;
border-left-width: 0;
border-left-width: 0;
border-radius: 0;
}
/* #ifndef APP-NVUE */
.uni-card--full:after {
border-radius: 0;
}
/* #endif */
.uni-ellipsis {
/* #ifndef APP-NVUE */
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
/* #endif */
/* #ifdef APP-NVUE */
lines: 1;
/* #endif */
}
</style>

View File

@ -0,0 +1,90 @@
{
"id": "uni-card",
"displayName": "uni-card 卡片",
"version": "1.3.1",
"description": "Card 组件,提供常见的卡片样式。",
"keywords": [
"uni-ui",
"uniui",
"card",
"",
"卡片"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-icons",
"uni-scss"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,12 @@
## Card 卡片
> **组件名uni-card**
> 代码块: `uCard`
卡片视图组件。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@ -0,0 +1,93 @@
## 2.2.62022-06-30
- 优化 组件样式调整了组件图标大小、高度、颜色等与uni-ui风格保持一致
## 2.2.52022-06-24
- 修复 日历顶部年月及底部确认未国际化 bug
## 2.2.42022-03-31
- 修复 Vue3 下动态赋值,单选类型未响应的 bug
## 2.2.32022-03-28
- 修复 Vue3 下动态赋值未响应的 bug
## 2.2.22021-12-10
- 修复 clear-icon 属性在小程序平台不生效的 bug
## 2.2.12021-12-10
- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug
## 2.2.02021-11-19
- 优化 组件UI并提供设计资源详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
## 2.1.52021-11-09
- 新增 提供组件设计资源,组件样式调整
## 2.1.42021-09-10
- 修复 hide-second 在移动端的 bug
- 修复 单选赋默认值时,赋值日期未高亮的 bug
- 修复 赋默认值时,移动端未正确显示时间的 bug
## 2.1.32021-09-09
- 新增 hide-second 属性,支持只使用时分,隐藏秒
## 2.1.22021-09-03
- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
- 优化 调整字号大小,美化日历界面
- 修复 因国际化导致的 placeholder 失效的 bug
## 2.1.12021-08-24
- 新增 支持国际化
- 优化 范围选择器在 pc 端过宽的问题
## 2.1.02021-08-09
- 新增 适配 vue3
## 2.0.192021-08-09
- 新增 支持作为 uni-forms 子组件相关功能
- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
## 2.0.182021-08-05
- 修复 type 属性动态赋值无效的 bug
- 修复 ‘确认’按钮被 tabbar 遮盖 bug
- 修复 组件未赋值时范围选左、右日历相同的 bug
## 2.0.172021-08-04
- 修复 范围选未正确显示当前值的 bug
- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
## 2.0.162021-07-21
- 新增 return-type 属性支持返回 date 日期对象
## 2.0.152021-07-14
- 修复 单选日期类型,初始赋值后不在当前日历的 bug
- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
- 优化 移动端移除显示框的清空按钮,无实际用途
## 2.0.142021-07-14
- 修复 组件赋值为空,界面未更新的 bug
- 修复 start 和 end 不能动态赋值的 bug
- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug
## 2.0.132021-07-08
- 修复 范围选择不能动态赋值的 bug
## 2.0.122021-07-08
- 修复 范围选择的初始时间在一个月内时造成无法选择的bug
## 2.0.112021-07-08
- 优化 弹出层在超出视窗边缘定位不准确的问题
## 2.0.102021-07-08
- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug
- 优化 弹出层在超出视窗边缘被遮盖的问题
## 2.0.92021-07-07
- 新增 maskClick 事件
- 修复 特殊情况日历 rpx 布局错误的 bugrpx -> px
- 修复 范围选择时清空返回值不合理的bug['', ''] -> []
## 2.0.82021-07-07
- 新增 日期时间显示框支持插槽
## 2.0.72021-07-01
- 优化 添加 uni-icons 依赖
## 2.0.62021-05-22
- 修复 图标在小程序上不显示的 bug
- 优化 重命名引用组件,避免潜在组件命名冲突
## 2.0.52021-05-20
- 优化 代码目录扁平化
## 2.0.42021-05-12
- 新增 组件示例地址
## 2.0.32021-05-10
- 修复 ios 下不识别 '-' 日期格式的 bug
- 优化 pc 下弹出层添加边框和阴影
## 2.0.22021-05-08
- 修复 在 admin 中获取弹出层定位错误的bug
## 2.0.12021-05-08
- 修复 type 属性向下兼容,默认值从 date 变更为 datetime
## 2.0.02021-04-30
- 支持日历形式的日期+时间的范围选择
> 注意此版本不向后兼容不再支持单独时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker
## 1.0.62021-03-18
- 新增 hide-second 属性,时间支持仅选择时、分
- 修复 选择跟显示的日期不一样的 bug
- 修复 chang事件触发2次的 bug
- 修复 分、秒 end 范围错误的 bug
- 优化 更好的 nvue 适配

View File

@ -0,0 +1,185 @@
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked-x':weeks.afterMultiple,
}" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
<view class="uni-calendar-item__weeks-box-item" :class="{
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover),
'uni-calendar-item--checked-range-text': checkHover,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
'uni-calendar-item--disable':weeks.disable,
}">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
</view>
<view :class="{'uni-calendar-item--isDay': weeks.isDay}"></view>
</view>
</template>
<script>
export default {
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
},
checkHover: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
},
handleMousemove(weeks) {
this.$emit('handleMouse', weeks)
}
}
}
</script>
<style lang="scss" >
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
margin: 1px 0;
position: relative;
}
.uni-calendar-item__weeks-box-text {
font-size: 14px;
// font-family: Lato-Bold, Lato;
font-weight: bold;
color: #455997;
}
.uni-calendar-item__weeks-lunar-text {
font-size: 12px;
color: #333;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
/* #ifdef H5 */
cursor: pointer;
/* #endif */
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: #dd524d;
}
.uni-calendar-item__weeks-box .uni-calendar-item--disable {
// background-color: rgba(249, 249, 249, $uni-opacity-disabled);
cursor: default;
}
.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
color: #D1D1D1;
}
.uni-calendar-item--isDay {
position: absolute;
top: 10px;
right: 17%;
background-color: #dd524d;
width:6px;
height: 6px;
border-radius: 50%;
}
.uni-calendar-item--extra {
color: #dd524d;
opacity: 0.8;
}
.uni-calendar-item__weeks-box .uni-calendar-item--checked {
background-color: #007aff;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #fff;
}
.uni-calendar-item--checked .uni-calendar-item--checked-text {
color: #fff;
}
.uni-calendar-item--multiple .uni-calendar-item--checked-range-text {
color: #333;
}
.uni-calendar-item--multiple {
background-color: #F6F7FC;
// color: #fff;
}
.uni-calendar-item--multiple .uni-calendar-item--before-checked,
.uni-calendar-item--multiple .uni-calendar-item--after-checked {
background-color: #409eff;
border-radius: 50%;
box-sizing: border-box;
border: 3px solid #F6F7FC;
}
.uni-calendar-item--before-checked .uni-calendar-item--checked-text,
.uni-calendar-item--after-checked .uni-calendar-item--checked-text {
color: #fff;
}
.uni-calendar-item--before-checked-x {
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
box-sizing: border-box;
background-color: #F6F7FC;
}
.uni-calendar-item--after-checked-x {
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
background-color: #F6F7FC;
}
</style>

View File

@ -0,0 +1,907 @@
<template>
<view class="uni-calendar" @mouseleave="leaveCale">
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
@click="clean"></view>
<view v-if="insert || show" class="uni-calendar__content"
:class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
<view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}">
<view v-if="left" class="uni-calendar__header-btn-box" @click.stop="pre">
<view class="uni-calendar__header-btn uni-calendar--left"></view>
</view>
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
<text
class="uni-calendar__header-text">{{ (nowDate.year||'') + yearText + ( nowDate.month||'') + monthText}}</text>
</picker>
<view v-if="right" class="uni-calendar__header-btn-box" @click.stop="next">
<view class="uni-calendar__header-btn uni-calendar--right"></view>
</view>
<view v-if="!insert" class="dialog-close" @click="clean">
<view class="dialog-close-plus" data-id="close"></view>
<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
</view>
<!-- <text class="uni-calendar__backtoday" @click="backtoday">回到今天</text> -->
</view>
<view class="uni-calendar__box">
<view v-if="showMonth" class="uni-calendar__box-bg">
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
</view>
<view class="uni-calendar__weeks" style="padding-bottom: 7px;">
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{MONText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
</view>
<view class="uni-calendar__weeks-day">
<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
</view>
</view>
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
:selected="selected" :lunar="lunar" :checkHover="range" @change="choiceDate"
@handleMouse="handleMouse">
</calendar-item>
</view>
</view>
</view>
<view v-if="!insert && !range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top"
style="padding: 0 80px;">
<view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view>
<time-picker type="time" :start="reactStartTime" :end="reactEndTime" v-model="time"
:disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style">
</time-picker>
</view>
<view v-if="!insert && range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top">
<view class="uni-date-changed--time-start">
<view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}}
</view>
<time-picker type="time" :start="reactStartTime" v-model="timeRange.startTime" :border="false"
:hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
</time-picker>
</view>
<uni-icons type="arrowthinright" color="#999" style="line-height: 50px;"></uni-icons>
<view class="uni-date-changed--time-end">
<view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
<time-picker type="time" :end="reactEndTime" v-model="timeRange.endTime" :border="false"
:hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style">
</time-picker>
</view>
</view>
<view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
<!-- <view class="uni-calendar__header-btn-box">
<text class="uni-calendar__button-text uni-calendar--fixed-width">{{okText}}</text>
</view> -->
<view class="uni-datetime-picker--btn" @click="confirm">{{confirmText}}</view>
</view>
</view>
</view>
</template>
<script>
import Calendar from './util.js';
import calendarItem from './calendar-item.vue'
import timePicker from './time-picker.vue'
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const {
t
} = initVueI18n(messages)
/**
* Calendar 日历
* @description 日历组件可以查看日期选择任意范围内的日期打点操作常用场景如酒店日期预订火车机票选择购买日期上下班打卡等
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
* @property {String} date 自定义当前时间默认为今天
* @property {Boolean} lunar 显示农历
* @property {String} startDate 日期选择范围-开始日期
* @property {String} endDate 日期选择范围-结束日期
* @property {Boolean} range 范围选择
* @property {Boolean} insert = [true|false] 插入模式,默认为false
* @value true 弹窗模式
* @value false 插入模式
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
* @property {Array} selected 打点期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
* @property {Boolean} showMonth 是否选择月份为背景
* @event {Function} change 日期改变`insert :ture` 时生效
* @event {Function} confirm 确认选择`insert :false` 时生效
* @event {Function} monthSwitch 切换月份时触发
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
*/
export default {
components: {
calendarItem,
timePicker
},
props: {
date: {
type: String,
default: ''
},
defTime: {
type: [String, Object],
default: ''
},
selectableTimes: {
type: [Object],
default () {
return {}
}
},
selected: {
type: Array,
default () {
return []
}
},
lunar: {
type: Boolean,
default: false
},
startDate: {
type: String,
default: ''
},
endDate: {
type: String,
default: ''
},
range: {
type: Boolean,
default: false
},
typeHasTime: {
type: Boolean,
default: false
},
insert: {
type: Boolean,
default: true
},
showMonth: {
type: Boolean,
default: true
},
clearDate: {
type: Boolean,
default: true
},
left: {
type: Boolean,
default: true
},
right: {
type: Boolean,
default: true
},
checkHover: {
type: Boolean,
default: true
},
hideSecond: {
type: [Boolean],
default: false
},
pleStatus: {
type: Object,
default () {
return {
before: '',
after: '',
data: [],
fulldate: ''
}
}
}
},
data() {
return {
show: false,
weeks: [],
calendar: {},
nowDate: '',
aniMaskShow: false,
firstEnter: true,
time: '',
timeRange: {
startTime: '',
endTime: ''
},
tempSingleDate: '',
tempRange: {
before: '',
after: ''
}
}
},
watch: {
date: {
immediate: true,
handler(newVal, oldVal) {
if (!this.range) {
this.tempSingleDate = newVal
setTimeout(() => {
this.init(newVal)
}, 100)
}
}
},
defTime: {
immediate: true,
handler(newVal, oldVal) {
if (!this.range) {
this.time = newVal
} else {
// console.log('-----', newVal);
this.timeRange.startTime = newVal.start
this.timeRange.endTime = newVal.end
}
}
},
startDate(val) {
this.cale.resetSatrtDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
endDate(val) {
this.cale.resetEndDate(val)
this.cale.setDate(this.nowDate.fullDate)
this.weeks = this.cale.weeks
},
selected(newVal) {
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
this.weeks = this.cale.weeks
},
pleStatus: {
immediate: true,
handler(newVal, oldVal) {
const {
before,
after,
fulldate,
which
} = newVal
this.tempRange.before = before
this.tempRange.after = after
setTimeout(() => {
if (fulldate) {
this.cale.setHoverMultiple(fulldate)
if (before && after) {
this.cale.lastHover = true
if (this.rangeWithinMonth(after, before)) return
this.setDate(before)
} else {
this.cale.setMultiple(fulldate)
this.setDate(this.nowDate.fullDate)
this.calendar.fullDate = ''
this.cale.lastHover = false
}
} else {
this.cale.setDefaultMultiple(before, after)
if (which === 'left') {
this.setDate(before)
this.weeks = this.cale.weeks
} else {
this.setDate(after)
this.weeks = this.cale.weeks
}
this.cale.lastHover = true
}
}, 16)
}
}
},
computed: {
reactStartTime() {
const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate
const res = activeDate === this.startDate ? this.selectableTimes.start : ''
return res
},
reactEndTime() {
const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate
const res = activeDate === this.endDate ? this.selectableTimes.end : ''
return res
},
/**
* for i18n
*/
selectDateText() {
return t("uni-datetime-picker.selectDate")
},
startDateText() {
return this.startPlaceholder || t("uni-datetime-picker.startDate")
},
endDateText() {
return this.endPlaceholder || t("uni-datetime-picker.endDate")
},
okText() {
return t("uni-datetime-picker.ok")
},
yearText() {
return t("uni-datetime-picker.year")
},
monthText() {
return t("uni-datetime-picker.month")
},
MONText() {
return t("uni-calender.MON")
},
TUEText() {
return t("uni-calender.TUE")
},
WEDText() {
return t("uni-calender.WED")
},
THUText() {
return t("uni-calender.THU")
},
FRIText() {
return t("uni-calender.FRI")
},
SATText() {
return t("uni-calender.SAT")
},
SUNText() {
return t("uni-calender.SUN")
},
confirmText() {
return t("uni-calender.confirm")
},
},
created() {
//
this.cale = new Calendar({
// date: new Date(),
selected: this.selected,
startDate: this.startDate,
endDate: this.endDate,
range: this.range,
// multipleStatus: this.pleStatus
})
//
// this.cale.setDate(this.date)
this.init(this.date)
// this.setDay
},
methods: {
leaveCale() {
this.firstEnter = true
},
handleMouse(weeks) {
if (weeks.disable) return
if (this.cale.lastHover) return
let {
before,
after
} = this.cale.multipleStatus
if (!before) return
this.calendar = weeks
//
this.cale.setHoverMultiple(this.calendar.fullDate)
this.weeks = this.cale.weeks
// hover
if (this.firstEnter) {
this.$emit('firstEnterCale', this.cale.multipleStatus)
this.firstEnter = false
}
},
rangeWithinMonth(A, B) {
const [yearA, monthA] = A.split('-')
const [yearB, monthB] = B.split('-')
return yearA === yearB && monthA === monthB
},
// 穿
clean() {
this.close()
},
clearCalender() {
if (this.range) {
this.timeRange.startTime = ''
this.timeRange.endTime = ''
this.tempRange.before = ''
this.tempRange.after = ''
this.cale.multipleStatus.before = ''
this.cale.multipleStatus.after = ''
this.cale.multipleStatus.data = []
this.cale.lastHover = false
} else {
this.time = ''
this.tempSingleDate = ''
}
this.calendar.fullDate = ''
this.setDate()
},
bindDateChange(e) {
const value = e.detail.value + '-1'
this.init(value)
},
/**
* 初始化日期显示
* @param {Object} date
*/
init(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.calendar = this.cale.getInfo(date)
},
// choiceDate(weeks) {
// if (weeks.disable) return
// this.calendar = weeks
// //
// this.cale.setMultiple(this.calendar.fullDate, true)
// this.weeks = this.cale.weeks
// this.tempSingleDate = this.calendar.fullDate
// this.tempRange.before = this.cale.multipleStatus.before
// this.tempRange.after = this.cale.multipleStatus.after
// this.change()
// },
/**
* 打开日历弹窗
*/
open() {
//
if (this.clearDate && !this.insert) {
this.cale.cleanMultipleStatus()
// this.cale.setDate(this.date)
this.init(this.date)
}
this.show = true
this.$nextTick(() => {
setTimeout(() => {
this.aniMaskShow = true
}, 50)
})
},
/**
* 关闭日历弹窗
*/
close() {
this.aniMaskShow = false
this.$nextTick(() => {
setTimeout(() => {
this.show = false
this.$emit('close')
}, 300)
})
},
/**
* 确认按钮
*/
confirm() {
this.setEmit('confirm')
this.close()
},
/**
* 变化触发
*/
change() {
if (!this.insert) return
this.setEmit('change')
},
/**
* 选择月份触发
*/
monthSwitch() {
let {
year,
month
} = this.nowDate
this.$emit('monthSwitch', {
year,
month: Number(month)
})
},
/**
* 派发事件
* @param {Object} name
*/
setEmit(name) {
let {
year,
month,
date,
fullDate,
lunar,
extraInfo
} = this.calendar
this.$emit(name, {
range: this.cale.multipleStatus,
year,
month,
date,
time: this.time,
timeRange: this.timeRange,
fulldate: fullDate,
lunar,
extraInfo: extraInfo || {}
})
},
/**
* 选择天触发
* @param {Object} weeks
*/
choiceDate(weeks) {
if (weeks.disable) return
this.calendar = weeks
this.calendar.userChecked = true
//
this.cale.setMultiple(this.calendar.fullDate, true)
this.weeks = this.cale.weeks
this.tempSingleDate = this.calendar.fullDate
this.tempRange.before = this.cale.multipleStatus.before
this.tempRange.after = this.cale.multipleStatus.after
this.change()
},
/**
* 回到今天
*/
backtoday() {
let date = this.cale.getDate(new Date()).fullDate
// this.cale.setDate(date)
this.init(date)
this.change()
},
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
//
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
//
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
},
/**
* 上个月
*/
pre() {
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
this.setDate(preDate)
this.monthSwitch()
},
/**
* 下个月
*/
next() {
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
this.setDate(nextDate)
this.monthSwitch()
},
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.cale.setDate(date)
this.weeks = this.cale.weeks
this.nowDate = this.cale.getInfo(date)
}
}
}
</script>
<style lang="scss" >
.uni-calendar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
}
.uni-calendar__mask {
position: fixed;
bottom: 0;
top: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.4);
transition-property: opacity;
transition-duration: 0.3s;
opacity: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--mask-show {
opacity: 1
}
.uni-calendar--fixed {
position: fixed;
bottom: calc(var(--window-bottom));
left: 0;
right: 0;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(460px);
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-calendar--ani-show {
transform: translateY(0);
}
.uni-calendar__content {
background-color: #fff;
}
.uni-calendar__content-mobile {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1);
}
.uni-calendar__header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
height: 50px;
}
.uni-calendar__header-mobile {
padding: 10px;
padding-bottom: 0;
}
.uni-calendar--fixed-top {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
border-top-color: rgba(0, 0, 0, 0.4);
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--fixed-width {
width: 50px;
}
.uni-calendar__backtoday {
position: absolute;
right: 0;
top: 25rpx;
padding: 0 5px;
padding-left: 10px;
height: 25px;
line-height: 25px;
font-size: 12px;
border-top-left-radius: 25px;
border-bottom-left-radius: 25px;
color: #fff;
background-color: #f1f1f1;
}
.uni-calendar__header-text {
text-align: center;
width: 100px;
font-size: 15px;
color: #666;
}
.uni-calendar__button-text {
text-align: center;
width: 100px;
font-size: 14px;
color: #007aff;
/* #ifndef APP-NVUE */
letter-spacing: 3px;
/* #endif */
}
.uni-calendar__header-btn-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
width: 50px;
height: 50px;
}
.uni-calendar__header-btn {
width: 9px;
height: 9px;
border-left-color: #808080;
border-left-style: solid;
border-left-width: 1px;
border-top-color: #555555;
border-top-style: solid;
border-top-width: 1px;
}
.uni-calendar--left {
transform: rotate(-45deg);
}
.uni-calendar--right {
transform: rotate(135deg);
}
.uni-calendar__weeks {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-calendar__weeks-item {
flex: 1;
}
.uni-calendar__weeks-day {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
height: 40px;
border-bottom-color: #F5F5F5;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.uni-calendar__weeks-day-text {
font-size: 12px;
color: #B2B2B2;
}
.uni-calendar__box {
position: relative;
// padding: 0 10px;
padding-bottom: 7px;
}
.uni-calendar__box-bg {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.uni-calendar__box-bg-text {
font-size: 200px;
font-weight: bold;
color: #999;
opacity: 0.1;
text-align: center;
/* #ifndef APP-NVUE */
line-height: 1;
/* #endif */
}
.uni-date-changed {
padding: 0 10px;
// line-height: 50px;
text-align: center;
color: #333;
border-top-color: #DCDCDC;
;
border-top-style: solid;
border-top-width: 1px;
flex: 1;
}
.uni-date-btn--ok {
padding: 20px 15px;
}
.uni-date-changed--time-start {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
}
.uni-date-changed--time-end {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
}
.uni-date-changed--time-date {
color: #999;
line-height: 50px;
margin-right: 5px;
// opacity: 0.6;
}
.time-picker-style {
// width: 62px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center
}
.mr-10 {
margin-right: 10px;
}
.dialog-close {
position: absolute;
top: 0;
right: 0;
bottom: 0;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
padding: 0 25px;
margin-top: 10px;
}
.dialog-close-plus {
width: 16px;
height: 2px;
background-color: #737987;
border-radius: 2px;
transform: rotate(45deg);
}
.dialog-close-rotate {
position: absolute;
transform: rotate(-45deg);
}
.uni-datetime-picker--btn {
border-radius: 100px;
height: 40px;
line-height: 40px;
background-color: #007aff;
color: #fff;
font-size: 16px;
letter-spacing: 2px;
}
/* #ifndef APP-NVUE */
.uni-datetime-picker--btn:active {
opacity: 0.7;
}
/* #endif */
</style>

View File

@ -0,0 +1,22 @@
{
"uni-datetime-picker.selectDate": "select date",
"uni-datetime-picker.selectTime": "select time",
"uni-datetime-picker.selectDateTime": "select datetime",
"uni-datetime-picker.startDate": "start date",
"uni-datetime-picker.endDate": "end date",
"uni-datetime-picker.startTime": "start time",
"uni-datetime-picker.endTime": "end time",
"uni-datetime-picker.ok": "ok",
"uni-datetime-picker.clear": "clear",
"uni-datetime-picker.cancel": "cancel",
"uni-datetime-picker.year": "-",
"uni-datetime-picker.month": "",
"uni-calender.MON": "MON",
"uni-calender.TUE": "TUE",
"uni-calender.WED": "WED",
"uni-calender.THU": "THU",
"uni-calender.FRI": "FRI",
"uni-calender.SAT": "SAT",
"uni-calender.SUN": "SUN",
"uni-calender.confirm": "confirm"
}

View File

@ -0,0 +1,8 @@
import en from './en.json'
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
export default {
en,
'zh-Hans': zhHans,
'zh-Hant': zhHant
}

View File

@ -0,0 +1,22 @@
{
"uni-datetime-picker.selectDate": "选择日期",
"uni-datetime-picker.selectTime": "选择时间",
"uni-datetime-picker.selectDateTime": "选择日期时间",
"uni-datetime-picker.startDate": "开始日期",
"uni-datetime-picker.endDate": "结束日期",
"uni-datetime-picker.startTime": "开始时间",
"uni-datetime-picker.endTime": "结束时间",
"uni-datetime-picker.ok": "确定",
"uni-datetime-picker.clear": "清除",
"uni-datetime-picker.cancel": "取消",
"uni-datetime-picker.year": "年",
"uni-datetime-picker.month": "月",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六",
"uni-calender.confirm": "确认"
}

View File

@ -0,0 +1,22 @@
{
"uni-datetime-picker.selectDate": "選擇日期",
"uni-datetime-picker.selectTime": "選擇時間",
"uni-datetime-picker.selectDateTime": "選擇日期時間",
"uni-datetime-picker.startDate": "開始日期",
"uni-datetime-picker.endDate": "結束日期",
"uni-datetime-picker.startTime": "開始时间",
"uni-datetime-picker.endTime": "結束时间",
"uni-datetime-picker.ok": "確定",
"uni-datetime-picker.clear": "清除",
"uni-datetime-picker.cancel": "取消",
"uni-datetime-picker.year": "年",
"uni-datetime-picker.month": "月",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六",
"uni-calender.confirm": "確認"
}

View File

@ -0,0 +1,45 @@
// #ifdef H5
export default {
name: 'Keypress',
props: {
disable: {
type: Boolean,
default: false
}
},
mounted () {
const keyNames = {
esc: ['Esc', 'Escape'],
tab: 'Tab',
enter: 'Enter',
space: [' ', 'Spacebar'],
up: ['Up', 'ArrowUp'],
left: ['Left', 'ArrowLeft'],
right: ['Right', 'ArrowRight'],
down: ['Down', 'ArrowDown'],
delete: ['Backspace', 'Delete', 'Del']
}
const listener = ($event) => {
if (this.disable) {
return
}
const keyName = Object.keys(keyNames).find(key => {
const keyName = $event.key
const value = keyNames[key]
return value === keyName || (Array.isArray(value) && value.includes(keyName))
})
if (keyName) {
// 避免和其他按键事件冲突
setTimeout(() => {
this.$emit(keyName, {})
}, 0)
}
}
document.addEventListener('keyup', listener)
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keyup', listener)
})
},
render: () => {}
}
// #endif

View File

@ -0,0 +1,927 @@
<template>
<view class="uni-datetime-picker">
<view @click="initTimePicker">
<slot>
<view class="uni-datetime-picker-timebox-pointer"
:class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
<text class="uni-datetime-picker-text">{{time}}</text>
<view v-if="!time" class="uni-datetime-picker-time">
<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
</view>
</view>
</slot>
</view>
<view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
<view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']"
:style="fixNvueBug">
<view class="uni-title">
<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
</view>
<view v-if="dateShow" class="uni-datetime-picker__container-box">
<picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
@change="bindDateChange">
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text class="uni-datetime-picker-sign sign-left">-</text>
<text class="uni-datetime-picker-sign sign-right">-</text>
</view>
<view v-if="timeShow" class="uni-datetime-picker__container-box">
<picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']"
:indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column>
<view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
<picker-view-column v-if="!hideSecond">
<view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index">
<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
</view>
</picker-view-column>
</picker-view>
<!-- 兼容 nvue 不支持伪类 -->
<text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text>
<text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text>
</view>
<view class="uni-datetime-picker-btn">
<view @click="clearTime">
<text class="uni-datetime-picker-btn-text">{{clearText}}</text>
</view>
<view class="uni-datetime-picker-btn-group">
<view class="uni-datetime-picker-cancel" @click="tiggerTimePicker">
<text class="uni-datetime-picker-btn-text">{{cancelText}}</text>
</view>
<view @click="setTime">
<text class="uni-datetime-picker-btn-text">{{okText}}</text>
</view>
</view>
</view>
</view>
<!-- #ifdef H5 -->
<!-- <keypress v-if="visible" @esc="tiggerTimePicker" @enter="setTime" /> -->
<!-- #endif -->
</view>
</template>
<script>
// #ifdef H5
import keypress from './keypress'
// #endif
import {
initVueI18n
} from '@dcloudio/uni-i18n'
import messages from './i18n/index.js'
const { t } = initVueI18n(messages)
/**
* DatetimePicker 时间选择器
* @description 可以同时选择日期和时间的选择器
* @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
* @property {String} type = [datetime | date | time] 显示模式
* @property {Boolean} multiple = [true|false] 是否多选
* @property {String|Number} value 默认值
* @property {String|Number} start 起始日期或时间
* @property {String|Number} end 起始日期或时间
* @property {String} return-type = [timestamp | string]
* @event {Function} change 选中发生变化触发
*/
export default {
name: 'UniDatetimePicker',
components: {
// #ifdef H5
keypress
// #endif
},
data() {
return {
indicatorStyle: `height: 50px;`,
visible: false,
fixNvueBug: {},
dateShow: true,
timeShow: true,
title: '日期和时间',
//
time: '',
//
year: 1920,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
//
startYear: 1920,
startMonth: 1,
startDay: 1,
startHour: 0,
startMinute: 0,
startSecond: 0,
//
endYear: 2120,
endMonth: 12,
endDay: 31,
endHour: 23,
endMinute: 59,
endSecond: 59,
}
},
props: {
type: {
type: String,
default: 'datetime'
},
value: {
type: [String, Number],
default: ''
},
modelValue: {
type: [String, Number],
default: ''
},
start: {
type: [Number, String],
default: ''
},
end: {
type: [Number, String],
default: ''
},
returnType: {
type: String,
default: 'string'
},
disabled: {
type: [Boolean, String],
default: false
},
border: {
type: [Boolean, String],
default: true
},
hideSecond: {
type: [Boolean, String],
default: false
}
},
watch: {
value: {
handler(newVal, oldVal) {
if (newVal) {
this.parseValue(this.fixIosDateFormat(newVal)) // iOSsafari
this.initTime(false)
} else {
this.time = ''
this.parseValue(Date.now())
}
},
immediate: true
},
type: {
handler(newValue) {
if (newValue === 'date') {
this.dateShow = true
this.timeShow = false
this.title = '日期'
} else if (newValue === 'time') {
this.dateShow = false
this.timeShow = true
this.title = '时间'
} else {
this.dateShow = true
this.timeShow = true
this.title = '日期和时间'
}
},
immediate: true
},
start: {
handler(newVal) {
this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') // iOSsafari
},
immediate: true
},
end: {
handler(newVal) {
this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') // iOSsafari
},
immediate: true
},
//
months(newVal) {
this.checkValue('month', this.month, newVal)
},
days(newVal) {
this.checkValue('day', this.day, newVal)
},
hours(newVal) {
this.checkValue('hour', this.hour, newVal)
},
minutes(newVal) {
this.checkValue('minute', this.minute, newVal)
},
seconds(newVal) {
this.checkValue('second', this.second, newVal)
}
},
computed: {
//
years() {
return this.getCurrentRange('year')
},
months() {
return this.getCurrentRange('month')
},
days() {
return this.getCurrentRange('day')
},
hours() {
return this.getCurrentRange('hour')
},
minutes() {
return this.getCurrentRange('minute')
},
seconds() {
return this.getCurrentRange('second')
},
// picker
ymd() {
return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay]
},
hms() {
return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond]
},
// date start
currentDateIsStart() {
return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay
},
// date end
currentDateIsEnd() {
return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay
},
//
minYear() {
return this.startYear
},
maxYear() {
return this.endYear
},
minMonth() {
if (this.year === this.startYear) {
return this.startMonth
} else {
return 1
}
},
maxMonth() {
if (this.year === this.endYear) {
return this.endMonth
} else {
return 12
}
},
minDay() {
if (this.year === this.startYear && this.month === this.startMonth) {
return this.startDay
} else {
return 1
}
},
maxDay() {
if (this.year === this.endYear && this.month === this.endMonth) {
return this.endDay
} else {
return this.daysInMonth(this.year, this.month)
}
},
minHour() {
if (this.type === 'datetime') {
if (this.currentDateIsStart) {
return this.startHour
} else {
return 0
}
}
if (this.type === 'time') {
return this.startHour
}
},
maxHour() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd) {
return this.endHour
} else {
return 23
}
}
if (this.type === 'time') {
return this.endHour
}
},
minMinute() {
if (this.type === 'datetime') {
if (this.currentDateIsStart && this.hour === this.startHour) {
return this.startMinute
} else {
return 0
}
}
if (this.type === 'time') {
if (this.hour === this.startHour) {
return this.startMinute
} else {
return 0
}
}
},
maxMinute() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd && this.hour === this.endHour) {
return this.endMinute
} else {
return 59
}
}
if (this.type === 'time') {
if (this.hour === this.endHour) {
return this.endMinute
} else {
return 59
}
}
},
minSecond() {
if (this.type === 'datetime') {
if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
return this.startSecond
} else {
return 0
}
}
if (this.type === 'time') {
if (this.hour === this.startHour && this.minute === this.startMinute) {
return this.startSecond
} else {
return 0
}
}
},
maxSecond() {
if (this.type === 'datetime') {
if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
return this.endSecond
} else {
return 59
}
}
if (this.type === 'time') {
if (this.hour === this.endHour && this.minute === this.endMinute) {
return this.endSecond
} else {
return 59
}
}
},
/**
* for i18n
*/
selectTimeText() {
return t("uni-datetime-picker.selectTime")
},
okText() {
return t("uni-datetime-picker.ok")
},
clearText() {
return t("uni-datetime-picker.clear")
},
cancelText() {
return t("uni-datetime-picker.cancel")
}
},
mounted() {
// #ifdef APP-NVUE
const res = uni.getSystemInfoSync();
this.fixNvueBug = {
top: res.windowHeight / 2,
left: res.windowWidth / 2
}
// #endif
},
methods: {
/**
* @param {Object} item
* 小于 10 在前面加个 0
*/
lessThanTen(item) {
return item < 10 ? '0' + item : item
},
/**
* 解析时分秒字符串例如00:00:00
* @param {String} timeString
*/
parseTimeType(timeString) {
if (timeString) {
let timeArr = timeString.split(':')
this.hour = Number(timeArr[0])
this.minute = Number(timeArr[1])
this.second = Number(timeArr[2])
}
},
/**
* 解析选择器初始值类型可以是字符串时间戳例如2000-10-02'08:30:00' 1610695109000
* @param {String | Number} datetime
*/
initPickerValue(datetime) {
let defaultValue = null
if (datetime) {
defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
} else {
defaultValue = Date.now()
defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
}
this.parseValue(defaultValue)
},
/**
* 初始值规则
* - 用户设置初始值 value
* - 设置了起始时间 start终止时间 end start < value < end初始值为 value 否则初始值为 start
* - 只设置了起始时间 start start < value初始值为 value否则初始值为 start
* - 只设置了终止时间 end value < end初始值为 value否则初始值为 end
* - 无起始终止时间则初始值为 value
* - 无初始值 value则初始值为当前本地时间 Date.now()
* @param {Object} value
* @param {Object} dateBase
*/
compareValueWithStartAndEnd(value, start, end) {
let winner = null
value = this.superTimeStamp(value)
start = this.superTimeStamp(start)
end = this.superTimeStamp(end)
if (start && end) {
if (value < start) {
winner = new Date(start)
} else if (value > end) {
winner = new Date(end)
} else {
winner = new Date(value)
}
} else if (start && !end) {
winner = start <= value ? new Date(value) : new Date(start)
} else if (!start && end) {
winner = value <= end ? new Date(value) : new Date(end)
} else {
winner = new Date(value)
}
return winner
},
/**
* 转换为可比较的时间戳接受日期时分秒时间戳
* @param {Object} value
*/
superTimeStamp(value) {
let dateBase = ''
if (this.type === 'time' && value && typeof value === 'string') {
const now = new Date()
const year = now.getFullYear()
const month = now.getMonth() + 1
const day = now.getDate()
dateBase = year + '/' + month + '/' + day + ' '
}
if (Number(value) && typeof value !== NaN) {
value = parseInt(value)
dateBase = 0
}
return this.createTimeStamp(dateBase + value)
},
/**
* 解析默认值 value字符串时间戳
* @param {Object} defaultTime
*/
parseValue(value) {
if (!value) {
return
}
if (this.type === 'time' && typeof value === "string") {
this.parseTimeType(value)
} else {
let defaultDate = null
defaultDate = new Date(value)
if (this.type !== 'time') {
this.year = defaultDate.getFullYear()
this.month = defaultDate.getMonth() + 1
this.day = defaultDate.getDate()
}
if (this.type !== 'date') {
this.hour = defaultDate.getHours()
this.minute = defaultDate.getMinutes()
this.second = defaultDate.getSeconds()
}
}
if (this.hideSecond) {
this.second = 0
}
},
/**
* 解析可选择时间范围 startend年月日字符串时间戳
* @param {Object} defaultTime
*/
parseDatetimeRange(point, pointType) {
//
if (!point) {
if (pointType === 'start') {
this.startYear = 1920
this.startMonth = 1
this.startDay = 1
this.startHour = 0
this.startMinute = 0
this.startSecond = 0
}
if (pointType === 'end') {
this.endYear = 2120
this.endMonth = 12
this.endDay = 31
this.endHour = 23
this.endMinute = 59
this.endSecond = 59
}
return
}
if (this.type === 'time') {
const pointArr = point.split(':')
this[pointType + 'Hour'] = Number(pointArr[0])
this[pointType + 'Minute'] = Number(pointArr[1])
this[pointType + 'Second'] = Number(pointArr[2])
} else {
if (!point) {
pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
return
}
if (Number(point) && Number(point) !== NaN) {
point = parseInt(point)
}
// datetime end ,
const hasTime = /[0-9]:[0-9]/
if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test(
point)) {
point = point + ' 23:59:59'
}
const pointDate = new Date(point)
this[pointType + 'Year'] = pointDate.getFullYear()
this[pointType + 'Month'] = pointDate.getMonth() + 1
this[pointType + 'Day'] = pointDate.getDate()
if (this.type === 'datetime') {
this[pointType + 'Hour'] = pointDate.getHours()
this[pointType + 'Minute'] = pointDate.getMinutes()
this[pointType + 'Second'] = pointDate.getSeconds()
}
}
},
//
getCurrentRange(value) {
const range = []
for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
range.push(i)
}
return range
},
//
capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
},
//
checkValue(name, value, values) {
if (values.indexOf(value) === -1) {
this[name] = values[0]
}
},
//
daysInMonth(year, month) { // Use 1 for January, 2 for February, etc.
return new Date(year, month, 0).getDate();
},
// iOSsafari
fixIosDateFormat(value) {
if (typeof value === 'string') {
value = value.replace(/-/g, '/')
}
return value
},
/**
* 生成时间戳
* @param {Object} time
*/
createTimeStamp(time) {
if (!time) return
if (typeof time === "number") {
return time
} else {
time = time.replace(/-/g, '/')
if (this.type === 'date') {
time = time + ' ' + '00:00:00'
}
return Date.parse(time)
}
},
/**
* 生成日期或时间的字符串
*/
createDomSting() {
const yymmdd = this.year +
'-' +
this.lessThanTen(this.month) +
'-' +
this.lessThanTen(this.day)
let hhmmss = this.lessThanTen(this.hour) +
':' +
this.lessThanTen(this.minute)
if (!this.hideSecond) {
hhmmss = hhmmss + ':' + this.lessThanTen(this.second)
}
if (this.type === 'date') {
return yymmdd
} else if (this.type === 'time') {
return hhmmss
} else {
return yymmdd + ' ' + hhmmss
}
},
/**
* 初始化返回值并抛出 change 事件
*/
initTime(emit = true) {
this.time = this.createDomSting()
if (!emit) return
if (this.returnType === 'timestamp' && this.type !== 'time') {
this.$emit('change', this.createTimeStamp(this.time))
this.$emit('input', this.createTimeStamp(this.time))
this.$emit('update:modelValue', this.createTimeStamp(this.time))
} else {
this.$emit('change', this.time)
this.$emit('input', this.time)
this.$emit('update:modelValue', this.time)
}
},
/**
* 用户选择日期或时间更新 data
* @param {Object} e
*/
bindDateChange(e) {
const val = e.detail.value
this.year = this.years[val[0]]
this.month = this.months[val[1]]
this.day = this.days[val[2]]
},
bindTimeChange(e) {
const val = e.detail.value
this.hour = this.hours[val[0]]
this.minute = this.minutes[val[1]]
this.second = this.seconds[val[2]]
},
/**
* 初始化弹出层
*/
initTimePicker() {
if (this.disabled) return
const value = this.fixIosDateFormat(this.value)
this.initPickerValue(value)
this.visible = !this.visible
},
/**
* 触发或关闭弹框
*/
tiggerTimePicker(e) {
this.visible = !this.visible
},
/**
* 用户点击清空按钮清空当前值
*/
clearTime() {
this.time = ''
this.$emit('change', this.time)
this.$emit('input', this.time)
this.$emit('update:modelValue', this.time)
this.tiggerTimePicker()
},
/**
* 用户点击确定按钮
*/
setTime() {
this.initTime()
this.tiggerTimePicker()
}
}
}
</script>
<style>
.uni-datetime-picker {
/* #ifndef APP-NVUE */
/* width: 100%; */
/* #endif */
}
.uni-datetime-picker-view {
height: 130px;
width: 270px;
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-item {
height: 50px;
line-height: 50px;
text-align: center;
font-size: 14px;
}
.uni-datetime-picker-btn {
margin-top: 60px;
/* #ifndef APP-NVUE */
display: flex;
cursor: pointer;
/* #endif */
flex-direction: row;
justify-content: space-between;
}
.uni-datetime-picker-btn-text {
font-size: 14px;
color: #007AFF;
}
.uni-datetime-picker-btn-group {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.uni-datetime-picker-cancel {
margin-right: 30px;
}
.uni-datetime-picker-mask {
position: fixed;
bottom: 0px;
top: 0px;
left: 0px;
right: 0px;
background-color: rgba(0, 0, 0, 0.4);
transition-duration: 0.3s;
z-index: 998;
}
.uni-datetime-picker-popup {
border-radius: 8px;
padding: 30px;
width: 270px;
/* #ifdef APP-NVUE */
height: 500px;
/* #endif */
/* #ifdef APP-NVUE */
width: 330px;
/* #endif */
background-color: #fff;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition-duration: 0.3s;
z-index: 999;
}
.fix-nvue-height {
/* #ifdef APP-NVUE */
height: 330px;
/* #endif */
}
.uni-datetime-picker-time {
color: grey;
}
.uni-datetime-picker-column {
height: 50px;
}
.uni-datetime-picker-timebox {
border: 1px solid #E5E5E5;
border-radius: 5px;
padding: 7px 10px;
/* #ifndef APP-NVUE */
box-sizing: border-box;
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-timebox-pointer {
/* #ifndef APP-NVUE */
cursor: pointer;
/* #endif */
}
.uni-datetime-picker-disabled {
opacity: 0.4;
/* #ifdef H5 */
cursor: not-allowed !important;
/* #endif */
}
.uni-datetime-picker-text {
font-size: 14px;
}
.uni-datetime-picker-sign {
position: absolute;
top: 53px;
/* 减掉 10px 的元素高度兼容nvue */
color: #999;
/* #ifdef APP-NVUE */
font-size: 16px;
/* #endif */
}
.sign-left {
left: 86px;
}
.sign-right {
right: 86px;
}
.sign-center {
left: 135px;
}
.uni-datetime-picker__container-box {
position: relative;
display: flex;
align-items: center;
justify-content: center;
margin-top: 40px;
}
.time-hide-second {
width: 180px;
}
</style>

View File

@ -0,0 +1,410 @@
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range,
// multipleStatus
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
// this.multipleStatus = multipleStatus
this.lastHover = false
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let isinfo = false
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
disableBefore = this.dateCompare(this.startDate, nowDate)
}
if (this.endDate) {
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
disableAfter = this.dateCompare(nowDate, this.endDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
month: full.month,
disable: !(disableBefore && disableAfter),
isDay,
userChecked: false
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
disable: true
})
}
return dateArr
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 比较真实起始日期
*/
isLogicBefore(currentDay, before, after) {
let logicBefore = before
if (before && after) {
logicBefore = this.dateCompare(before, after) ? before : after
}
return this.dateEqual(logicBefore, currentDay)
}
isLogicAfter(currentDay, before, after) {
let logicAfter = after
if (before && after) {
logicAfter = this.dateCompare(before, after) ? after : before
}
return this.dateEqual(logicAfter, currentDay)
}
/**
* 获取日期范围内所有日期
* @param {Object} begin
* @param {Object} end
*/
geDateAll(begin, end) {
var arr = []
var ab = begin.split('-')
var ae = end.split('-')
var db = new Date()
db.setFullYear(ab[0], ab[1] - 1, ab[2])
var de = new Date()
de.setFullYear(ae[0], ae[1] - 1, ae[2])
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
for (var k = unixDb; k <= unixDe;) {
k = k + 24 * 60 * 60 * 1000
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
if (!this.lastHover) {
this.lastHover = true
return
}
this.multipleStatus.before = fullDate
this.multipleStatus.after = ''
this.multipleStatus.data = []
this.multipleStatus.fulldate = ''
this.lastHover = false
} else {
if (!before) {
this.multipleStatus.before = fullDate
this.lastHover = false
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
.before);
}
this.lastHover = true
}
}
this._getWeek(fullDate)
}
/**
* 鼠标 hover 更新多选状态
*/
setHoverMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (this.lastHover) return
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
} else {
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
}
}
this._getWeek(fullDate)
}
/**
* 更新默认值多选状态
*/
setDefaultMultiple(before, after) {
this.multipleStatus.before = before
this.multipleStatus.after = after
if (before && after) {
if (this.dateCompare(before, after)) {
this.multipleStatus.data = this.geDateAll(before, after);
this._getWeek(after)
} else {
this.multipleStatus.data = this.geDateAll(after, before);
this._getWeek(before)
}
}
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
fullDate,
year,
month,
date,
day
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar

View File

@ -0,0 +1,90 @@
{
"id": "uni-datetime-picker",
"displayName": "uni-datetime-picker 日期选择器",
"version": "2.2.6",
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
"keywords": [
"uni-datetime-picker",
"uni-ui",
"uniui",
"日期时间选择器",
"日期时间"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss",
"uni-icons"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,21 @@
> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容不再支持单独的时间选择type=time及相关的 hide-second 属性(时间选可使用内置组件 picker。若仍需使用旧版本可在插件市场下载*非uni_modules版本*,旧版本将不再维护`
## DatetimePicker 时间选择器
> **组件名uni-datetime-picker**
> 代码块: `uDatetimePicker`
该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。
若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
**_点击 picker 默认值规则_**
- 若设置初始值 value, 会显示在 picker 显示框中
- 若无初始值 value则初始值 value 为当前本地时间 Date.now() 但不会显示在 picker 显示框中
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

View File

@ -0,0 +1,2 @@
## 0.0.12022-07-22
- 初始化

View File

@ -0,0 +1,167 @@
<template>
<view class="uni-section">
<view class="uni-section-header" @click="onClick">
<view class="uni-section-header__decoration" v-if="type" :class="type" />
<slot v-else name="decoration"></slot>
<view class="uni-section-header__content">
<text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text>
<text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text>
</view>
<view class="uni-section-header__slot-right">
<slot name="right"></slot>
</view>
</view>
<view class="uni-section-content" :style="{padding: _padding}">
<slot />
</view>
</view>
</template>
<script>
/**
* Section 标题栏
* @description 标题栏
* @property {String} type = [line|circle|square] 标题装饰类型
* @value line 竖线
* @value circle 圆形
* @value square 正方形
* @property {String} title 主标题
* @property {String} titleFontSize 主标题字体大小
* @property {String} titleColor 主标题字体颜色
* @property {String} subTitle 副标题
* @property {String} subTitleFontSize 副标题字体大小
* @property {String} subTitleColor 副标题字体颜色
* @property {String} padding 默认插槽 padding
*/
export default {
name: 'UniSection',
emits:['click'],
props: {
type: {
type: String,
default: ''
},
title: {
type: String,
required: true,
default: ''
},
titleFontSize: {
type: String,
default: '14px'
},
titleColor:{
type: String,
default: '#333'
},
subTitle: {
type: String,
default: ''
},
subTitleFontSize: {
type: String,
default: '12px'
},
subTitleColor: {
type: String,
default: '#999'
},
padding: {
type: [Boolean, String],
default: false
}
},
computed:{
_padding(){
if(typeof this.padding === 'string'){
return this.padding
}
return this.padding?'10px':''
}
},
watch: {
title(newVal) {
if (uni.report && newVal !== '') {
uni.report('title', newVal)
}
}
},
methods: {
onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" >
$uni-primary: #2979ff !default;
.uni-section {
background-color: #fff;
.uni-section-header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
padding: 12px 10px;
font-weight: normal;
&__decoration{
margin-right: 6px;
background-color: $uni-primary;
&.line {
width: 4px;
height: 12px;
border-radius: 10px;
}
&.circle {
width: 8px;
height: 8px;
border-top-right-radius: 50px;
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
}
&.square {
width: 8px;
height: 8px;
}
}
&__content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
flex: 1;
color: #333;
.distraction {
flex-direction: row;
align-items: center;
}
&-sub {
margin-top: 2px;
}
}
&__slot-right{
font-size: 14px;
}
}
.uni-section-content{
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,87 @@
{
"id": "uni-section",
"displayName": "uni-section 标题栏",
"version": "0.0.1",
"description": "标题栏组件",
"keywords": [
"uni-ui",
"uniui",
"标题栏"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [
"uni-scss"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,8 @@
## Section 标题栏
> **组件名uni-section**
> 代码块: `uSection`
uni-section 组件主要用于文章、列表详情等标题展示
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-section)
#### 如使用过程中有任何问题或者您对uni-ui有一些好的建议欢迎加入 uni-ui 交流群871950839

38
utils/check.js Normal file
View File

@ -0,0 +1,38 @@
/*
检测正整数, 不能为0
*/
export const checkNumber1 = /^[0-9]*[1-9][0-9]*$/;
/*
检测最多2位小数(包含0)
*/
export const checkNumber2 = /^(-){0,1}(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/;
/*
检测最多2位小数(包含0) 正数
*/
export const checkNumber2_1 = /^(([1-9]{1}\d*)|(0{1}))(\.\d{1,2})?$/;
/*
检测最多3位小数(包含0)
*/
export const checkNumber3 = /^(-){0,1}(([1-9]{1}\d*)|(0{1}))(\.\d{1,3})?$/;
/*
检测最多4位小数(包含0)
*/
export const checkNumber4 = /^(-){0,1}(([1-9]{1}\d*)|(0{1}))(\.\d{1,4})?$/;
/*
检测最多5位小数(包含0)
*/
export const checkNumber5 = /^(-){0,1}(([1-9]{1}\d*)|(0{1}))(\.\d{1,5})?$/;
/*
检测最多10位小数(包含0)
*/
export const checkNumber10 = /^(-){0,1}(([1-9]{1}\d*)|(0{1}))(\.\d{1,10})?$/;
// 邮箱正则表达式
export const emailRegular = /^[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*@[a-zA-Z0-9]+([-_.][a-zA-Z0-9]+)*\.[a-z]{2,}$/;
// 电话号正则表达式
export const phoneRegular = /^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$/;

13
utils/nonNullCheck.js Normal file
View File

@ -0,0 +1,13 @@
function nonNullCheck(params){
if(params === "" || params === undefined || params === null) {
return false;
}
params = params + "";
if(!params.trim()){
return false;
}
return true;
}
export default nonNullCheck;