代码更新
This commit is contained in:
parent
2c47202245
commit
35db378ced
5
App.vue
5
App.vue
|
@ -25,7 +25,10 @@
|
|||
|
||||
@import "static/css/base.css";
|
||||
@import "static/css/style.scss";
|
||||
|
||||
/deep/.u-action-sheet__item-wrap {
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
||||
@import url('static/iconfont/iconfont.css')
|
||||
</style>
|
25
api/oa.js
25
api/oa.js
|
@ -12,7 +12,7 @@ export const getSalaryDeatilsApi = () => oahttp.get('/user/info')
|
|||
//获取部门
|
||||
export const getDepartmentApi = () => oahttp.get('/index/get_department_tree')
|
||||
//获取部门人员
|
||||
export const getDepartmentPersonApi = (data) => oahttp.get('/index/get_employee', data)
|
||||
export const getDepartmentPersonApi = (data) => oahttp.get('/common/get_employee', data)
|
||||
//新建任务
|
||||
export const addNewTaskApi = (data) => oahttp.post('/task/add', data)
|
||||
//获取文档列表
|
||||
|
@ -74,8 +74,7 @@ export const comanyerlist = (data) => oahttp.get('/user_user/index',data)
|
|||
|
||||
//获取企业员工详情
|
||||
export const comanyerview= (data) => oahttp.get('/user_user/view',data)
|
||||
|
||||
|
||||
//编辑员工状态
|
||||
//新增编辑员工
|
||||
export const addcomanyer= (data) => oahttp.post('/user_user/add',data)
|
||||
|
||||
|
@ -171,7 +170,7 @@ export const appexpenseindex = (data) => oahttp.get('/finance_expense/index',dat
|
|||
//获取我处理的报销记录
|
||||
export const apexpenselist = (data) => oahttp.get('/finance_expense/list',data)
|
||||
//获取抄送的报销记录
|
||||
export const appexpensecopy = (data) => oahttp.get('/oa_approve/copy',data)
|
||||
export const appexpensecopy = (data) => oahttp.get('/finance_expense/copy',data)
|
||||
|
||||
//报销类型
|
||||
export const appexpensecate = (data) => oahttp.get('/common/get_expense_cate',data)
|
||||
|
@ -230,18 +229,30 @@ export const tasksubjec = (data) => oahttp.get('/common/get_task_list',data)
|
|||
//获取发票开票
|
||||
export const invoicecheckedlist = (data) => oahttp.get('/finance_invoice/checkedlist',data)
|
||||
//发票开票/修改
|
||||
export const financeopen = (data) => oahttp.get('/finance_invoice/open',data)
|
||||
|
||||
export const financeopen = (data) => oahttp.post('/finance_invoice/open',data)
|
||||
|
||||
|
||||
//发票作废
|
||||
export const tovoid = (data) => oahttp.post('/finance_invoice/tovoid',data)
|
||||
|
||||
//发票反作废
|
||||
export const novoid = (data) => oahttp.get('/finance_invoice/novoid',data)
|
||||
export const novoid = (data) => oahttp.post('/finance_invoice/novoid',data)
|
||||
|
||||
//获取发票到账信息
|
||||
export const incomeflow = (data) => oahttp.get('/finance_income/index',data)
|
||||
|
||||
//获取发票到账详情
|
||||
export const incomeview = (data) => oahttp.get('/finance_income/view',data)
|
||||
|
||||
//新增发票到账
|
||||
export const addincome = (data) => oahttp.post('/finance_income/add',data)
|
||||
|
||||
|
||||
//删除发票到账
|
||||
export const deleteincome = (data) => oahttp.post('/finance_income/delete',data)
|
||||
|
||||
// 获取未读消息数
|
||||
export const msgcount = (data) => oahttp.get('/common/msg_count',data)
|
||||
|
||||
export const deletemessage = (data) => oahttp.post('/message_index/delete',data)
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ function oaUploads(src, type) {
|
|||
// console.log('上传', type === 'img' ? '图片' : '视频', ':', src)
|
||||
|
||||
let a = uni.uploadFile({
|
||||
url: HTTP_REQUEST_URL_THREE + '/api/home_index/upload',
|
||||
url: HTTP_REQUEST_URL_THREE + '/api/common/upload',
|
||||
filePath: src,
|
||||
name: 'file',
|
||||
header: header,
|
||||
|
|
32
pages.json
32
pages.json
|
@ -24,10 +24,7 @@
|
|||
"path": "pages/oaLogin/editpwd",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改密码",
|
||||
"app-plus": {
|
||||
"titleNView": false,
|
||||
"bounce": "none"
|
||||
},
|
||||
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
|
@ -62,8 +59,9 @@
|
|||
{
|
||||
"path": "pages/examine/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "审批"
|
||||
|
||||
"navigationBarTitleText": "审批",
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -77,15 +75,18 @@
|
|||
{
|
||||
"path": "pages/leaveapplication/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "申请"
|
||||
|
||||
"navigationBarTitleText": "申请",
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
"path": "pages/resources/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "人力资源"
|
||||
"navigationBarTitleText": "人力资源",
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
|
||||
}
|
||||
},
|
||||
|
@ -194,6 +195,7 @@
|
|||
"path": "pages/addquest/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新增任务",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#3274F9"
|
||||
|
||||
}
|
||||
|
@ -211,6 +213,7 @@
|
|||
"path": "pages/reimbursementrecord/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "报销打款",
|
||||
"navigationBarTextStyle": "white",
|
||||
"navigationBarBackgroundColor": "#3274F9"
|
||||
|
||||
}
|
||||
|
@ -384,7 +387,7 @@
|
|||
{
|
||||
"path": "pages/addfinance/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "编辑到账",
|
||||
"navigationBarTitleText": "新增到账",
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
|
@ -404,8 +407,15 @@
|
|||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/waitlist/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "待办列表",
|
||||
"navigationBarBackgroundColor": "#3274F9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
"globalStyle": {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<view class="acea-row row-middle">
|
||||
<text class="item-name">发票id:</text>
|
||||
|
||||
<input placeholder="请输入发票id" type="text" readonly v-model="merchantData.id">
|
||||
<input placeholder="请输入发票id" type="text" readonly disabled v-model="typename" @click="show4=true">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
@ -26,7 +26,7 @@
|
|||
<view class="acea-row row-middle">
|
||||
<text class="item-name">备注:</text>
|
||||
|
||||
<input placeholder="请输入备注" type="text" readonly v-model="merchantData.remarks">
|
||||
<input placeholder="请输入备注" type="text" readonly v-model="remarks">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
@ -51,7 +51,9 @@
|
|||
</view>
|
||||
</form>
|
||||
|
||||
<u-action-sheet :show="show3" :actions="actions3" title="请选择任务性质" @close="show3 = false" @select="Select3">
|
||||
<u-action-sheet :show="show3" :actions="actions3" title="请选择发票类型" @close="show3 = false" @select="Select3">
|
||||
</u-action-sheet>
|
||||
<u-action-sheet :show="show4" :actions="actions4" title="请选择发票列表" @close="show4 = false" @select="Select4">
|
||||
</u-action-sheet>
|
||||
<u-datetime-picker :show="endmonth" mode="date" closeOnClickOverlay @confirm="end_monthConfirm"
|
||||
@cancel="end_monthClose" @close="end_monthClose"></u-datetime-picker>
|
||||
|
@ -67,8 +69,9 @@
|
|||
|
||||
<script>
|
||||
import {
|
||||
userpositiongroup,
|
||||
financeopen
|
||||
|
||||
addincome,
|
||||
invoicecheckedlist
|
||||
} from '@/api/oa.js'
|
||||
import {
|
||||
Toast
|
||||
|
@ -84,10 +87,11 @@
|
|||
name: "",
|
||||
merchantData: {
|
||||
|
||||
|
||||
},
|
||||
show3: false,
|
||||
show4: false,
|
||||
amount: '',
|
||||
remarks:'',
|
||||
actions3: [{
|
||||
name: '部分到账',
|
||||
id: 1
|
||||
|
@ -100,23 +104,35 @@
|
|||
}],
|
||||
|
||||
uidtype: 1,
|
||||
actions4: [],
|
||||
typename:''
|
||||
};
|
||||
},
|
||||
onLoad(option) {
|
||||
|
||||
|
||||
this.type = option.type
|
||||
if (this.type == 1) {
|
||||
|
||||
// this.buname=
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.datalist()
|
||||
|
||||
},
|
||||
methods: {
|
||||
async datalist() {
|
||||
let res = await invoicecheckedlist({
|
||||
page: 1,
|
||||
limit: 1000
|
||||
});
|
||||
console.log(res)
|
||||
const detailTypeOptions = res.data.data.map((step, index) => {
|
||||
return {
|
||||
name: step.name +','+ step.amount,
|
||||
id: step.id,
|
||||
};
|
||||
});
|
||||
// console.log(detailTypeOptions)
|
||||
this.actions4=detailTypeOptions
|
||||
},
|
||||
//结束月份
|
||||
end_monthClose() {
|
||||
this.endmonth = false
|
||||
|
@ -140,16 +156,24 @@
|
|||
this.uidtype = e.id
|
||||
this.name = e.name
|
||||
},
|
||||
Select4(e) {
|
||||
// console.log(e)
|
||||
this.merchantData.inid = e.id
|
||||
|
||||
this.typename = e.name
|
||||
},
|
||||
validateForm: function() {
|
||||
this.merchantData.amount = []
|
||||
this.merchantData.remarks=[]
|
||||
this.merchantData.amount.push(this.amount)
|
||||
this.merchantData.remarks.push(this.remarks)
|
||||
let that = this,
|
||||
value = that.merchantData;
|
||||
// console.log(this.merchantData)
|
||||
if (!value.enter_type) return Toast(
|
||||
'请选择到账类型'
|
||||
);
|
||||
if (!value.id) return Toast('请输入发票 id');
|
||||
if (!value.inid) return Toast('请输入发票 id');
|
||||
if (!value.enter_time) return Toast('请输入到账时间');
|
||||
if (!value.amount.length > 0) return Toast('请输入金额');
|
||||
that.validate = true;
|
||||
|
@ -161,7 +185,7 @@
|
|||
let that = this
|
||||
console.log(that.validate)
|
||||
if (this.validateForm() && this.validate) {
|
||||
const res = await financeopen(this.merchantData)
|
||||
const res = await addincome(this.merchantData)
|
||||
Toast(res.msg);
|
||||
if (res.code == 0) {
|
||||
uni.navigateBack({
|
||||
|
|
|
@ -176,25 +176,33 @@
|
|||
</u-picker>
|
||||
|
||||
|
||||
<u-datetime-picker :show="porject1month" mode="date" closeOnClickOverlay @confirm="porject1_monthConfirm"
|
||||
<!-- <u-datetime-picker :show="porject1month" mode="date" closeOnClickOverlay @confirm="porject1_monthConfirm"
|
||||
@cancel="porject1_monthClose" @close="porject1_monthClose"></u-datetime-picker>
|
||||
<u-datetime-picker :show="porject2month" mode="date" closeOnClickOverlay @confirm="porject2_monthConfirm"
|
||||
@cancel="porject2_monthClose" @close="porject2_monthClose"></u-datetime-picker>
|
||||
|
||||
|
||||
<u-datetime-picker :show="endmonth" mode="date" closeOnClickOverlay @confirm="end_monthConfirm"
|
||||
@cancel="end_monthClose" @close="end_monthClose"></u-datetime-picker>
|
||||
<u-datetime-picker :show="startmonth" mode="date" closeOnClickOverlay @confirm="start_monthConfirm"
|
||||
@cancel="start_monthClose" @close="start_monthClose"></u-datetime-picker>
|
||||
<view class="content-bottom"> -->
|
||||
|
||||
<u-calendar :show="porject1month" mode='single' @confirm="porject1_monthConfirm"
|
||||
@close="porject1_monthClose"></u-calendar>
|
||||
<u-calendar :show="porject2month" mode='single' @confirm="porject2_monthConfirm"></u-calendar>
|
||||
<u-calendar :show="endmonth" mode='single' @confirm="end_monthConfirm" @close="end_monthClose"></u-calendar>
|
||||
<u-calendar :show="startmonth" mode='single' @confirm="start_monthConfirm"
|
||||
@close="start_monthClose"></u-calendar>
|
||||
|
||||
|
||||
|
||||
<view class="content-bottom">
|
||||
|
||||
|
||||
|
||||
<view class="content-bottom-two" @click="submit">
|
||||
立即提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
@ -272,8 +280,7 @@
|
|||
companyrole: '',
|
||||
start_time: '',
|
||||
end_time: ''
|
||||
}
|
||||
, // 实施阶段
|
||||
}, // 实施阶段
|
||||
{
|
||||
name: '验收阶段',
|
||||
companyrole: '',
|
||||
|
@ -506,10 +513,8 @@
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
let dat = await getemployee({
|
||||
did: codelist[1][0].id
|
||||
did: codelist[0][0].id
|
||||
})
|
||||
|
||||
codelist[2] = dat.data.map((item) => {
|
||||
|
@ -655,7 +660,8 @@
|
|||
|
||||
porject1_monthConfirm(e) {
|
||||
this.porject1month = false
|
||||
this.phases[this.num].start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
// this.phases[this.num].start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.phases[this.num].start_time = e[0]
|
||||
this.$nextTick(() => {
|
||||
this.validatePhaseTime(this.num)
|
||||
})
|
||||
|
@ -664,7 +670,8 @@
|
|||
},
|
||||
porject2_monthConfirm(e) {
|
||||
this.porject2month = false
|
||||
this.phases[this.num].end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
// this.phases[this.num].end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.phases[this.num].end_time = e[0]
|
||||
this.$nextTick(() => {
|
||||
this.validatePhaseTime(this.num)
|
||||
})
|
||||
|
@ -687,8 +694,8 @@
|
|||
},
|
||||
end_monthConfirm(e) {
|
||||
this.endmonth = false
|
||||
this.merchantData.end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
|
||||
// this.merchantData.end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.merchantData.end_time = e[0]
|
||||
},
|
||||
//开始月份
|
||||
start_monthClose() {
|
||||
|
@ -697,7 +704,8 @@
|
|||
},
|
||||
start_monthConfirm(e) {
|
||||
this.startmonth = false
|
||||
this.merchantData.start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
// this.merchantData.start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.merchantData.start_time = e[0]
|
||||
},
|
||||
|
||||
validatePhaseTime(index) {
|
||||
|
@ -707,7 +715,7 @@
|
|||
Toast('项目时间范围不合法')
|
||||
}
|
||||
const phase = this.phases[index]
|
||||
console.log(phase.start_time, this.merchantData.start_time)
|
||||
// console.log(phase.start_time, this.merchantData.start_time)
|
||||
// 检查当前阶段的时间是否超出项目时间范围
|
||||
if (new Date(phase.start_time) < new Date(this.merchantData.start_time) || new Date(
|
||||
phase.end_time) >
|
||||
|
|
|
@ -25,14 +25,15 @@
|
|||
closeOnClickOverlay @close="flag1 = false" @change="columnCode" @confirm="confirm"
|
||||
keyName="name" :defaultIndex='defaultIndex'>
|
||||
</u-picker>
|
||||
|
||||
<!-- 协作人 -->
|
||||
<u-picker :show="flag2" :columns="columns3" ref="uPicker5" @cancel="cancel"
|
||||
<u-picker :show="flag2" :columns="columns4" ref="uPicker5" @cancel="cancel"
|
||||
@close="flag2 = false" @confirm="confirm1" @change="columnCode1" keyName="name"
|
||||
closeOnClickOverlay :defaultIndex='defaultIndex1'>
|
||||
</u-picker>
|
||||
|
||||
<!-- 验收人 -->
|
||||
<u-picker :show="flag3" :columns="columns3" ref="uPicker6" @cancel="cancel"
|
||||
<u-picker :show="flag3" :columns="columns5" ref="uPicker6" @cancel="cancel"
|
||||
@close="flag3 = false" @confirm="confirm" @change="columnCode2" keyName="name"
|
||||
closeOnClickOverlay :defaultIndex='defaultIndex2'>
|
||||
</u-picker>
|
||||
|
@ -56,8 +57,8 @@
|
|||
</u-form-item>
|
||||
<!-- 月份 -->
|
||||
<u-form-item label="预估工时:" prop="userInfo.plan_hours" borderBottom
|
||||
@click="endmonth = true; hideKeyboard()" ref="item5">
|
||||
<u--input v-model="model1.userInfo.plan_hours" disabled disabledColor="#ffffff"
|
||||
ref="item5">
|
||||
<u--input v-model="model1.userInfo.plan_hours" disabledColor="#ffffff"
|
||||
placeholder="请选择" border="none"></u--input>
|
||||
</u-form-item>
|
||||
<!-- 关联项目 -->
|
||||
|
@ -110,9 +111,11 @@
|
|||
@confirm="start_timeConfirm" @cancel="start_timeClose"
|
||||
@close="start_timeClose"></u-datetime-picker> -->
|
||||
<!-- 结束日期 -->
|
||||
<u-datetime-picker :show="endtime" :value="end_time" mode="datetime" closeOnClickOverlay
|
||||
<!-- <u-datetime-picker :show="endtime" :value="end_time" mode="datetime" closeOnClickOverlay
|
||||
@confirm="end_timeConfirm" @cancel="end_timeClose"
|
||||
@close="end_timeClose"></u-datetime-picker>
|
||||
@close="end_timeClose"></u-datetime-picker> -->
|
||||
<u-calendar :show="endtime"
|
||||
color="#f56c6c" mode='single' @close="end_timeClose" @confirm="end_timeConfirm" @cancel="end_timeClose"></u-calendar>
|
||||
<!-- 结束月份 -->
|
||||
<u-datetime-picker :show="endmonth" :value="plan_hours" mode="date" closeOnClickOverlay
|
||||
@confirm="end_monthConfirm" @cancel="end_monthClose"
|
||||
|
@ -157,6 +160,8 @@
|
|||
defaultIndex1: [0, 0, 0],
|
||||
defaultIndex2: [0, 0, 0],
|
||||
columns3: [],
|
||||
columns4: [],
|
||||
columns5: [],
|
||||
director_name: '', //指派给
|
||||
assist_admin_names: '', //协作人
|
||||
priority_status: '', //优先级,
|
||||
|
@ -496,8 +501,9 @@
|
|||
},
|
||||
end_timeConfirm(e) {
|
||||
this.endtime = false
|
||||
this.model1.userInfo.end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.$refs.form1.validateField('userInfo.end_time')
|
||||
console.log(e)
|
||||
this.model1.userInfo.end_time = e[0]
|
||||
// this.$refs.form1.validateField('userInfo.end_time')
|
||||
},
|
||||
//结束月份
|
||||
end_monthClose() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<view class="application">
|
||||
<block v-for="item in appDataList" :key="item.title">
|
||||
<block v-for="(item,i) in appDataList" :key="i">
|
||||
<view class="apply_line">
|
||||
<view class="title flex_a_c">
|
||||
<view class="text flex_a_c">
|
||||
|
@ -71,9 +71,20 @@
|
|||
|
||||
},
|
||||
lineCentClick(item) {
|
||||
if(item.id=='9998'){
|
||||
uni.navigateTo({
|
||||
url: '/pages/resources/index'
|
||||
})
|
||||
}else if(item.id=='9999'){
|
||||
uni.navigateTo({
|
||||
url: '/pages/finance/index'
|
||||
})
|
||||
}else{
|
||||
uni.navigateTo({
|
||||
url: '/pages/leaveapplication/index?type='+item.id
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -23,11 +23,12 @@
|
|||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.status==1?'#34A853':item.status==2?'#F9AA32':item.status==3?'#F02828':''}">
|
||||
|
||||
<text v-if='item.status==1'>已通过</text>
|
||||
<text v-if='item.status==2'>待审批</text>
|
||||
<text v-if='item.status==3'>审批拒绝</text>
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
|
@ -84,23 +85,7 @@
|
|||
],
|
||||
list2: [],
|
||||
num: 0,
|
||||
btnList: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
height: '100rpx',
|
||||
width: '100rpx',
|
||||
bgColor: '#ed656d',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList: [],
|
||||
loadConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
|
@ -248,8 +233,15 @@
|
|||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.loadConfig.status = "loading"
|
||||
|
||||
if (this.num == 0) {
|
||||
this.initList()
|
||||
} else if (this.num == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
@ -262,7 +254,7 @@
|
|||
})
|
||||
},
|
||||
tian(item) {
|
||||
console.log(item)
|
||||
// console.log(item)
|
||||
if (this.num == 1) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/leave_request/index?type=' + item.id
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<view class="middle-three">
|
||||
|
||||
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j' @click="deleteDepartment(items.id)">
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j'>
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList'>
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
|
@ -22,30 +22,19 @@
|
|||
<view class="middle-threeb-a">
|
||||
|
||||
<view class="threeb-a-b">
|
||||
|
||||
<view class="name">开票人:<text>{{items.open_name}}</text></view>
|
||||
<view class="name">开票银行:<text>{{items.invoice_account}}</text></view>
|
||||
<view class="name">开票金额(元):<text>{{items.amount}}</text></view>
|
||||
|
||||
<!-- <view class="achor">{{items.name2}}</view> -->
|
||||
<!-- <view class="middle-edit" @click="editpart(items)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(items)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="middle-threeb-b">
|
||||
{{items.name}}
|
||||
</view> -->
|
||||
|
||||
</view>
|
||||
|
||||
</liu-swipe-action>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -98,7 +87,9 @@
|
|||
<script>
|
||||
import {
|
||||
incomeflow,
|
||||
deleteincomeflow
|
||||
deleteincome,
|
||||
incomeview,
|
||||
invoicecheckedlist,
|
||||
} from '@/api/oa.js'
|
||||
import {
|
||||
HTTP_REQUEST_URL
|
||||
|
@ -112,14 +103,6 @@
|
|||
return {
|
||||
show: false,
|
||||
btnList: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
height: '100rpx',
|
||||
|
@ -163,13 +146,14 @@
|
|||
uni.stopPullDownRefresh()
|
||||
},
|
||||
methods: {
|
||||
|
||||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list = [];
|
||||
await this.getDocumentList();
|
||||
},
|
||||
//获取任务
|
||||
//获取发票
|
||||
async getDocumentList() {
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
|
@ -197,15 +181,21 @@
|
|||
})
|
||||
},
|
||||
//删除弹窗
|
||||
clickItem(data) {
|
||||
async clickItem(data) {
|
||||
// console.log(e)
|
||||
|
||||
if (data.id == 2) {
|
||||
let res = await incomeview({
|
||||
id: this.list[data.index].id
|
||||
})
|
||||
let data1=res.data
|
||||
|
||||
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(this.list[data.index].id)
|
||||
|
||||
this.deleteDepartment(this.list[data.index].id,data1.income[0].inid)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -216,10 +206,11 @@
|
|||
},
|
||||
|
||||
//删除
|
||||
async deleteDepartment(id) {
|
||||
async deleteDepartment(id,inid) {
|
||||
|
||||
const res = await deleteincomeflow({
|
||||
id: id
|
||||
const res = await deleteincome({
|
||||
id: id,
|
||||
inid:inid
|
||||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
|
@ -499,15 +490,15 @@
|
|||
background: #3274F9;
|
||||
border-radius: 60rpx 60rpx;
|
||||
z-index: 99999;
|
||||
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
margin-top: 25rpx;
|
||||
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
margin-left: -193rpx;
|
||||
bottom: 100rpx;
|
||||
|
||||
.middle-two-img {
|
||||
width: 23rpx;
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
<view class="middle-three">
|
||||
|
||||
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j' @click="deleteDepartment(items.id)">
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList'>
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j'>
|
||||
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList1'
|
||||
v-if="items.check_status==2">
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
{{items.name}}
|
||||
|
@ -20,29 +22,98 @@
|
|||
|
||||
<view class="middle-threeba">
|
||||
<view class="middle-threeb-a">
|
||||
<!-- check_status 状态:0待审核,1审核中,2审核通过,3审核不通过,4已撤销,5已开具,10已作废 -->
|
||||
<view class="threeb-a-b">
|
||||
<view class="name">开票人:<text>{{items.open_name}}</text></view>
|
||||
<view class="name">所属部门:<text>{{items.department_name}}</text></view>
|
||||
<view class="name">开票金额(元):<text>{{items.amount}}</text></view>
|
||||
<view class="name">
|
||||
开票类型:<text>{{items.invoice_type==1?'增值税专用发票':items.invoice_type==2?'普通发票':'专用发票'}}</text>
|
||||
</view>
|
||||
<!-- <view class="achor">{{items.name2}}</view> -->
|
||||
<!-- <view class="middle-edit" @click="editpart(items)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(items)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</liu-swipe-action>
|
||||
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList'
|
||||
v-if="items.check_status==5">
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
{{items.name}}
|
||||
</view>
|
||||
<view class="title-status">
|
||||
{{items.create_time}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="middle-threeba">
|
||||
<view class="middle-threeb-a">
|
||||
<!-- check_status 状态:0待审核,1审核中,2审核通过,3审核不通过,4已撤销,5已开具,10已作废 -->
|
||||
<view class="threeb-a-b">
|
||||
|
||||
<view class="name">开票人:<text>{{items.open_name}}</text></view>
|
||||
<view class="name">所属部门:<text>{{items.department_name}}</text></view>
|
||||
<view class="name">开票金额(元):<text>{{items.amount}}</text></view>
|
||||
|
||||
<view class="name">
|
||||
开票类型:<text>{{items.invoice_type==1?'增值税专用发票':items.invoice_type==2?'普通发票':'专用发票'}}</text>
|
||||
</view>
|
||||
<!-- <view class="achor">{{items.name2}}</view> -->
|
||||
<view class="middle-edit" @click="editpart(items)">
|
||||
<!-- <view class="middle-edit" @click="editpart(items)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(items)">
|
||||
删除
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="middle-threeb-b">
|
||||
{{items.name}}
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</liu-swipe-action>
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList2'
|
||||
v-if="items.check_status==10">
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
{{items.name}}
|
||||
</view>
|
||||
<view class="title-status">
|
||||
{{items.create_time}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="middle-threeba">
|
||||
<view class="middle-threeb-a">
|
||||
<!-- check_status 状态:0待审核,1审核中,2审核通过,3审核不通过,4已撤销,5已开具,10已作废 -->
|
||||
<view class="threeb-a-b">
|
||||
|
||||
<view class="name">开票人:<text>{{items.open_name}}</text></view>
|
||||
<view class="name">所属部门:<text>{{items.department_name}}</text></view>
|
||||
<view class="name">开票金额(元):<text>{{items.amount}}</text></view>
|
||||
<view class="name">
|
||||
开票类型:<text>{{items.invoice_type==1?'增值税专用发票':items.invoice_type==2?'普通发票':'专用发票'}}</text>
|
||||
</view>
|
||||
<!-- <view class="achor">{{items.name2}}</view> -->
|
||||
<!-- <view class="middle-edit" @click="editpart(items)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(items)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</liu-swipe-action>
|
||||
</view>
|
||||
|
||||
|
||||
|
@ -81,12 +152,7 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle-two">
|
||||
<view class="middle-two-img">
|
||||
<image src="@/static/images/ja2.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="" @click="adddepart">新建任务</view>
|
||||
</view>
|
||||
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list.length==0" text="没有信息"
|
||||
icon="/static/empty/data.png"></u-empty>
|
||||
<u-loadmore v-else :status="loadConfig.status" :loading-text="loadConfig.loadingText"
|
||||
|
@ -98,7 +164,8 @@
|
|||
<script>
|
||||
import {
|
||||
invoicecheckedlist,
|
||||
tovoid
|
||||
tovoid,
|
||||
novoid
|
||||
} from '@/api/oa.js'
|
||||
import {
|
||||
HTTP_REQUEST_URL
|
||||
|
@ -128,6 +195,32 @@
|
|||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList2: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '4',
|
||||
name: '反作废',
|
||||
height: '100rpx',
|
||||
width: '100rpx',
|
||||
bgColor: '#ed656d',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList1: [{
|
||||
id: '3',
|
||||
name: '开票',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
loadConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
|
@ -198,11 +291,10 @@
|
|||
},
|
||||
//删除弹窗
|
||||
clickItem(data) {
|
||||
// console.log(e)
|
||||
|
||||
console.log(data)
|
||||
if (data.id == 2) {
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
content: '确定要作废发票吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(this.list[data.index].id)
|
||||
|
@ -210,12 +302,25 @@
|
|||
}
|
||||
})
|
||||
|
||||
} else if (data.id == 4) {
|
||||
uni.showModal({
|
||||
content: '确定要反作废发票吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment1(this.list[data.index].id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} else if (data.id == 3) {
|
||||
|
||||
this.editpart(this.list[data.index], '3')
|
||||
} else {
|
||||
this.editpart(this.list[data.index])
|
||||
this.editpart(this.list[data.index], '1')
|
||||
}
|
||||
},
|
||||
|
||||
//删除
|
||||
//作废
|
||||
async deleteDepartment(id) {
|
||||
|
||||
const res = await tovoid({
|
||||
|
@ -229,15 +334,31 @@
|
|||
}
|
||||
Toast(res.msg);
|
||||
|
||||
},
|
||||
//反作废
|
||||
async deleteDepartment1(id) {
|
||||
|
||||
const res = await novoid({
|
||||
id: id
|
||||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
|
||||
this.initList()
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
},
|
||||
taskDetail(item) {
|
||||
|
||||
},
|
||||
//编辑任务
|
||||
editpart(item) {
|
||||
editpart(item, type) {
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/addfinanceincome/index??type=' + 2 + "&data=" + encodeURIComponent(JSON.stringify(
|
||||
url: '/pages/addfinanceincome/index??type=' + type + "&data=" + encodeURIComponent(JSON
|
||||
.stringify(
|
||||
item))
|
||||
})
|
||||
},
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
</view>
|
||||
<view class="work">
|
||||
<view class="wr_item">
|
||||
<view class="wr_t_left">(技术部):</view>
|
||||
<view class="wr_t_right">技术专业</view>
|
||||
<view class="wr_t_left">{{ oaUserInfo.department_name}}</view>
|
||||
<!-- <view class="wr_t_right">技术专业</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -48,8 +48,7 @@
|
|||
</view>
|
||||
</view>
|
||||
<view class="content-banner">
|
||||
<view class="content-banner-title" style="display: flex;justify-content: space-between;">
|
||||
|
||||
<view class="content-banner-title" style="display: flex;justify-content: space-between;" @click="daiban">
|
||||
<view class="">
|
||||
待办事项
|
||||
</view>
|
||||
|
@ -58,21 +57,24 @@
|
|||
<text class="iconfont icon-xiangyou" style="margin-top: 5rpx;margin-right: 20rpx;"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-banner-detail" v-for="(item,k) in list2" :key='k' v-if="isshow1">
|
||||
<view class="">
|
||||
<view class="content-banner-detail" v-for="(item,k) in list2" :key='k' @click="spclickItem(item)">
|
||||
<view class="banner-detail">
|
||||
<view class="banner-detail-title">
|
||||
提醒
|
||||
</view>
|
||||
<view class="banner-detail-detail">
|
||||
{{item.title}}
|
||||
你有一个{{item.flow_type}}审批
|
||||
</view>
|
||||
</view>
|
||||
<view class="iconfont icon-xiangyou" style="margin-top: 5rpx;">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="bootom-top-three" v-else>
|
||||
|
||||
<view class="bootom-top-three" v-else>
|
||||
<scroll-view scroll-x="true" scroll-left="0" class="top-three">
|
||||
<view class="top_users-header">
|
||||
<view class="">
|
||||
|
@ -92,7 +94,7 @@
|
|||
</view>
|
||||
<view class="top_users-header">
|
||||
<view class="">
|
||||
{{list6.approve}}
|
||||
{{list6.invoice}}
|
||||
</view>
|
||||
<view class="title3">
|
||||
待审发票
|
||||
|
@ -100,14 +102,14 @@
|
|||
</view>
|
||||
<view class="top_users-header">
|
||||
<view class="">
|
||||
{{list6.approve}}
|
||||
{{list6.task}}
|
||||
</view>
|
||||
<view class="title4">
|
||||
待回款
|
||||
待完成任务
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="content-sort">
|
||||
<view class="content-sort-con" v-for="(item,l) in list3" :key="l" @click="appcenter(item,l)">
|
||||
|
@ -149,7 +151,7 @@
|
|||
<view class="bootom-top-one">
|
||||
我的任务
|
||||
</view>
|
||||
<view class="bootom-top-two">
|
||||
<view class="bootom-top-two" @click="geng">
|
||||
<text>更多</text>
|
||||
<text class="iconfont icon-xiangyou" style="font-size: 25rpx;"></text>
|
||||
</view>
|
||||
|
@ -232,7 +234,7 @@
|
|||
img: require('@/static/images/s4.png')
|
||||
|
||||
}, {
|
||||
name: '请假申请',
|
||||
name: '外出申请',
|
||||
img: require('@/static/images/s3.png')
|
||||
|
||||
}, {
|
||||
|
@ -244,8 +246,8 @@
|
|||
img: require('@/static/images/s8.png')
|
||||
|
||||
}, {
|
||||
name: '用章申请',
|
||||
img: require('@/static/images/s7.png')
|
||||
name: '发票申请',
|
||||
img: require('@/static/images/fa.png')
|
||||
|
||||
}, {
|
||||
name: '报销申请',
|
||||
|
@ -256,28 +258,7 @@
|
|||
img: require('@/static/images/s1.png')
|
||||
|
||||
}],
|
||||
list4: [{
|
||||
name: '紧急',
|
||||
con: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
status: '紧急紧',
|
||||
con1: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
con2: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
|
||||
}, {
|
||||
name: '紧急',
|
||||
con: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
status: '紧急紧',
|
||||
con1: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
con2: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
|
||||
}, {
|
||||
name: '紧急',
|
||||
con: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
status: '紧急紧',
|
||||
con1: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
con2: '紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急紧急',
|
||||
|
||||
}],
|
||||
list4: [],
|
||||
HTTP_IMG_URL: '',
|
||||
list5: [],
|
||||
list6: {},
|
||||
|
@ -323,8 +304,13 @@
|
|||
},
|
||||
async getDtlist1() {
|
||||
let res = await tasksubjec()
|
||||
|
||||
this.list2 = res.data.data
|
||||
this.list2 = res.data
|
||||
},
|
||||
spclickItem(item){
|
||||
console.log(item)
|
||||
uni.navigateTo({
|
||||
url:'/pages/leave_request/index?type='+item.id
|
||||
})
|
||||
},
|
||||
//获取任务
|
||||
async getDocumentList2() {
|
||||
|
@ -338,10 +324,23 @@
|
|||
this.list4 = res.data.data
|
||||
|
||||
},
|
||||
|
||||
//待办
|
||||
daiban(){
|
||||
uni.navigateTo({
|
||||
url:'/pages/waitlist/index'
|
||||
})
|
||||
},
|
||||
|
||||
//任务
|
||||
geng() {
|
||||
uni.switchTab({
|
||||
url: '/pages/oaTask/oaTask'
|
||||
})
|
||||
},
|
||||
//获取部门
|
||||
async getList() {
|
||||
const res = await getdatatotal()
|
||||
|
||||
this.list = res.data
|
||||
},
|
||||
//列表
|
||||
|
@ -382,7 +381,7 @@
|
|||
break;
|
||||
case "task":
|
||||
uni.switchTab({
|
||||
url: '/oaTask/oaTask'
|
||||
url: '/pages/oaTask/oaTask'
|
||||
})
|
||||
break;
|
||||
case "article":
|
||||
|
@ -403,43 +402,44 @@
|
|||
gongao1() {
|
||||
this.isshow1 = !this.isshow1
|
||||
},
|
||||
|
||||
//应用中心
|
||||
appcenter(item, i) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/com_approve'
|
||||
url: '/pages/leaveapplication/index?type=1'
|
||||
})
|
||||
break;
|
||||
case 1:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/leaveapplication/index?type=2'
|
||||
})
|
||||
break;
|
||||
case 2:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/leaveapplication/index?type=3'
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/leaveapplication/index?type=15'
|
||||
})
|
||||
break;
|
||||
case 4:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/leaveapplication/index?type=7'
|
||||
})
|
||||
break;
|
||||
|
||||
case 5:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/invoice/add'
|
||||
})
|
||||
break;
|
||||
case 6:
|
||||
uni.navigateTo({
|
||||
url: '/pages/appcenter/index'
|
||||
url: '/pages/reimbursementapplication/index'
|
||||
})
|
||||
break;
|
||||
case 7:
|
||||
|
@ -523,13 +523,11 @@
|
|||
.top_class {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 28rpx 28rpx;
|
||||
|
||||
.top_class-one {
|
||||
flex-basis: 25%;
|
||||
|
||||
|
||||
margin-bottom: 42rpx;
|
||||
text-align: center;
|
||||
|
||||
|
|
|
@ -49,25 +49,25 @@
|
|||
<view class="title">电话号码:</view>
|
||||
<input type="text" v-model="listobj.invoice_phone" placeholder="电话号码">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">纳税人识别号 :</view>
|
||||
<input type="text" v-model="listobj.invoice_tax" placeholder="纳税人识别号">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">开户行:</view>
|
||||
<input type="text" v-model="listobj.invoice_bank" placeholder="开户行">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行账号:</view>
|
||||
<input type="text" v-model="listobj.invoice_account" placeholder="银行账号">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行营业网点 :</view>
|
||||
<input type="text" v-model="listobj.invoice_banking" placeholder="银行营业网点">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">地址:</view>
|
||||
<input type="text" v-model="listobj.invoice_address" placeholder="地址">
|
||||
</view>
|
||||
|
@ -221,14 +221,19 @@
|
|||
columns: [],
|
||||
check_admin_name: '',
|
||||
copy_names: '',
|
||||
isshow:true,
|
||||
columns1: [{
|
||||
name: '企业',
|
||||
name: '增值税专用发票',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
name: '个人',
|
||||
name: '普通发票',
|
||||
id: 2,
|
||||
},{
|
||||
name: '专用发票',
|
||||
id: 3
|
||||
}
|
||||
|
||||
],
|
||||
list: [{
|
||||
cate_title: "",
|
||||
|
@ -386,6 +391,11 @@
|
|||
deliveryWayChangetwo(e) {
|
||||
|
||||
this.listobj.type = e.detail.value
|
||||
if(e.detail.value==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
},
|
||||
//弹窗显示
|
||||
leavaShow(item, i) {
|
||||
|
@ -564,6 +574,10 @@
|
|||
position: relative;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
/deep/.u-action-sheet item-wrap{
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
|
||||
.leave_box,
|
||||
.flow_path {
|
||||
|
|
|
@ -49,25 +49,25 @@
|
|||
<view class="title">电话号码:</view>
|
||||
<input type="text" v-model="listobj.invoice_phone" placeholder="电话号码">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">纳税人识别号 :</view>
|
||||
<input type="text" v-model="listobj.invoice_tax" placeholder="纳税人识别号">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">开户行:</view>
|
||||
<input type="text" v-model="listobj.invoice_bank" placeholder="开户行">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行账号:</view>
|
||||
<input type="text" v-model="listobj.invoice_account" placeholder="银行账号">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行营业网点 :</view>
|
||||
<input type="text" v-model="listobj.invoice_banking" placeholder="银行营业网点">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">地址:</view>
|
||||
<input type="text" v-model="listobj.invoice_address" placeholder="地址">
|
||||
</view>
|
||||
|
@ -222,14 +222,19 @@
|
|||
columns: [],
|
||||
check_admin_name: '',
|
||||
copy_names: '',
|
||||
isshow:true,
|
||||
columns1: [{
|
||||
name: '企业',
|
||||
name: '增值税专用发票',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
name: '个人',
|
||||
name: '普通发票',
|
||||
id: 2,
|
||||
},{
|
||||
name: '专用发票',
|
||||
id: 3
|
||||
}
|
||||
|
||||
],
|
||||
list: [{
|
||||
cate_title: "",
|
||||
|
@ -287,6 +292,11 @@
|
|||
this.listobj.type=res.data.detail.type
|
||||
this.selected = res.data.detail.type.toString()
|
||||
// console.log(res.data.detail.type)
|
||||
if( res.data.detail.type==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.list = [{
|
||||
|
@ -409,6 +419,13 @@
|
|||
deliveryWayChangetwo(e) {
|
||||
|
||||
this.listobj.type = e.detail.value
|
||||
|
||||
|
||||
if(e.detail.value==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
},
|
||||
//弹窗显示
|
||||
leavaShow(item, i) {
|
||||
|
@ -587,7 +604,10 @@
|
|||
position: relative;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
/deep/.u-action-sheet__item-wrap {
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.leave_box,
|
||||
.flow_path {
|
||||
width: 100%;
|
||||
|
|
|
@ -48,25 +48,25 @@
|
|||
<view class="title">电话号码:</view>
|
||||
<input type="text" v-model="listobj.invoice_phone" placeholder="电话号码">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">纳税人识别号 :</view>
|
||||
<input type="text" v-model="listobj.invoice_tax" placeholder="纳税人识别号">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">开户行:</view>
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title" v-if="isshow">开户行:</view>
|
||||
<input type="text" v-model="listobj.invoice_bank" placeholder="开户行">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行账号:</view>
|
||||
<input type="text" v-model="listobj.invoice_account" placeholder="银行账号">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行营业网点 :</view>
|
||||
<input type="text" v-model="listobj.invoice_banking" placeholder="银行营业网点">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">地址:</view>
|
||||
<input type="text" v-model="listobj.invoice_address" placeholder="地址">
|
||||
</view>
|
||||
|
@ -112,8 +112,8 @@
|
|||
</view>
|
||||
</view>-->
|
||||
<!-- </view> -->
|
||||
<view class="flow_path">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="listobj.check_status!= 4&& ktype!=0">
|
||||
<view class="flow_path" v-if="listobj.check_status!= 5&&listobj.check_status!= 2&& ktype!=0">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="listobj.check_status!= 4">
|
||||
<view class="title" style="width: 200rpx;">撤回意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入撤回意见" />
|
||||
</view>
|
||||
|
@ -145,7 +145,7 @@
|
|||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="ktype!=0">
|
||||
<view class="" v-if="ktype!=0&&listobj.check_status!= 5&&listobj.check_status!= 2 ">
|
||||
<view class="bot_btn" v-if="listobj.check_status!= 4">
|
||||
<!-- <view class="reset" @click="reset">重置</view> -->
|
||||
<view class="submit_btn" @click="submiteBtn">撤回</view>
|
||||
|
@ -258,14 +258,19 @@
|
|||
columns: [],
|
||||
check_admin_name: '',
|
||||
copy_names: '',
|
||||
isshow:true,
|
||||
columns1: [{
|
||||
name: '企业',
|
||||
name: '增值税专用发票',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
name: '个人',
|
||||
name: '普通发票',
|
||||
id: 2,
|
||||
},{
|
||||
name: '专用发票',
|
||||
id: 3
|
||||
}
|
||||
|
||||
],
|
||||
list: [{
|
||||
cate_title: "",
|
||||
|
@ -315,9 +320,19 @@
|
|||
this.check_record = res.data.check_record
|
||||
this.check_admin_name = res.data.detail.check_user
|
||||
this.copy_names = res.data.detail.copy_user
|
||||
this.selected= res.data.detail.type.toString()
|
||||
|
||||
|
||||
if( res.data.detail.type==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
if( res.data.detail.type==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
|
||||
},
|
||||
reset() {
|
||||
this.list = [{
|
||||
|
@ -439,6 +454,11 @@
|
|||
deliveryWayChangetwo(e) {
|
||||
|
||||
this.listobj.type = e.detail.value
|
||||
if(e.detail.value==2){
|
||||
this.isshow=false
|
||||
}else{
|
||||
this.isshow=true
|
||||
}
|
||||
},
|
||||
//弹窗显示
|
||||
leavaShow(item, i) {
|
||||
|
|
|
@ -48,25 +48,25 @@
|
|||
<view class="title">电话号码:</view>
|
||||
<input type="text" v-model="listobj.invoice_phone" placeholder="电话号码">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">纳税人识别号 :</view>
|
||||
<input type="text" v-model="listobj.invoice_tax" placeholder="纳税人识别号">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">开户行:</view>
|
||||
<input type="text" v-model="listobj.invoice_bank" placeholder="开户行">
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行账号:</view>
|
||||
<input type="text" v-model="listobj.invoice_account" placeholder="银行账号">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">银行营业网点 :</view>
|
||||
<input type="text" v-model="listobj.invoice_banking" placeholder="银行营业网点">
|
||||
</view>
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="cont_cell" v-if="isshow">
|
||||
<view class="title">地址:</view>
|
||||
<input type="text" v-model="listobj.invoice_address" placeholder="地址">
|
||||
</view>
|
||||
|
@ -131,7 +131,7 @@
|
|||
|
||||
<view class="cont_cell">
|
||||
<view class="title">审核状态:</view>
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':'撤销审核'}}
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':listobj.check_status=='4'?'已撤销':listobj.check_status=='5'?'已开具':'已作废'}}
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">当前审核人:</view>
|
||||
|
@ -142,7 +142,7 @@
|
|||
<input type="text" v-model="copy_names" placeholder="请选择" disabled>
|
||||
</view>
|
||||
|
||||
<view class="" >
|
||||
<view class="" v-if="listobj.check_status!= 5&&listobj.check_status!= 2">
|
||||
<view class="title" style="margin-bottom: 30rpx;">审核节点:</view>
|
||||
<radio-group class="select_group" @change="deliveryWayChangetwo1">
|
||||
<label class="radio_select" style="margin-right:15rpx;display: flex; margin-bottom: 30rpx;">
|
||||
|
@ -163,13 +163,14 @@
|
|||
</radio-group>
|
||||
</view>
|
||||
</block>
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="listobj.check_status!= 4">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;"
|
||||
v-if="listobj.check_status!= 4&&listobj.check_status!= 5&&listobj.check_status!= 2">
|
||||
<view class="title" style="width: 200rpx;">审核意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入审核意见" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bot_btn">
|
||||
<view class="bot_btn" v-if="listobj.check_status!= 5&&listobj.check_status!= 2">
|
||||
<view class="reset" @click="appflowcheck()">拒绝</view>
|
||||
<view class="submit_btn" @click=" appflowcheck1()">通过</view>
|
||||
</view>
|
||||
|
@ -275,14 +276,19 @@
|
|||
columns: [],
|
||||
check_admin_name: '',
|
||||
copy_names: '',
|
||||
isshow: true,
|
||||
columns1: [{
|
||||
name: '企业',
|
||||
name: '增值税专用发票',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
name: '个人',
|
||||
name: '普通发票',
|
||||
id: 2,
|
||||
}, {
|
||||
name: '专用发票',
|
||||
id: 3
|
||||
}
|
||||
|
||||
],
|
||||
list: [{
|
||||
cate_title: "",
|
||||
|
@ -333,8 +339,11 @@
|
|||
this.admin_name = res.data.detail.check_user
|
||||
this.copy_names = res.data.detail.copy_user
|
||||
this.selected = res.data.detail.type.toString()
|
||||
|
||||
|
||||
if (res.data.detail.type == 2) {
|
||||
this.isshow = false
|
||||
} else {
|
||||
this.isshow = true
|
||||
}
|
||||
},
|
||||
reset() {
|
||||
this.list = [{
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<view class="content-middle-one">
|
||||
<view class="middle-one" v-for="(item,k) in list2" @click="tian(item)">
|
||||
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList'>
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList3' v-if="item.check_status==5">
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
|
@ -23,24 +23,109 @@
|
|||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.status==1?'#34A853':item.status==2?'#F9AA32':item.status==3?'#F02828':''}">
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
<text v-if='item.check_status==10'>已作废</text>
|
||||
|
||||
<text v-if='item.status==1'>已通过</text>
|
||||
<text v-if='item.status==2'>待审批</text>
|
||||
<text v-if='item.status==3'>审批拒绝</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开票金额:{{item.amount}}</view>
|
||||
<view class="middle-one-time">审核人{{item.check_user}}</view>
|
||||
</liu-swipe-action>
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view> -->
|
||||
<!--<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view> -->
|
||||
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList2' v-else-if="item.check_status==10">
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
<text v-if='item.check_status==10'>已作废</text>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开票金额:{{item.amount}}</view>
|
||||
<view class="middle-one-time">审核人{{item.check_user}}</view>
|
||||
</liu-swipe-action>
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList1' v-else-if="item.check_status==2">
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
<text v-if='item.check_status==10'>已作废</text>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开票金额:{{item.amount}}</view>
|
||||
<view class="middle-one-time">审核人{{item.check_user}}</view>
|
||||
</liu-swipe-action>
|
||||
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList' v-else>
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
<text v-if='item.check_status==10'>已作废</text>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开票金额:{{item.amount}}</view>
|
||||
<view class="middle-one-time">审核人{{item.check_user}}</view>
|
||||
</liu-swipe-action>
|
||||
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list2.length==0" text="没有信息"
|
||||
|
@ -57,8 +142,11 @@
|
|||
|
||||
import {
|
||||
|
||||
invoiceindex,invoicelist,invoicecopy
|
||||
|
||||
invoiceindex,
|
||||
invoicelist,
|
||||
invoicecopy,
|
||||
tovoid,
|
||||
novoid
|
||||
} from '@/api/oa.js'
|
||||
|
||||
export default {
|
||||
|
@ -81,23 +169,50 @@
|
|||
],
|
||||
list2: [],
|
||||
num: 0,
|
||||
btnList: [{
|
||||
btnList: [],
|
||||
btnList3: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
name: '编辑开票',
|
||||
width: '130rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
name: '作废',
|
||||
height: '100rpx',
|
||||
width: '100rpx',
|
||||
bgColor: '#ed656d',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList2: [{
|
||||
id: '1',
|
||||
name: '编辑开票',
|
||||
width: '130rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '4',
|
||||
name: '反作废',
|
||||
height: '100rpx',
|
||||
width: '100rpx',
|
||||
bgColor: '#ed656d',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList1: [{
|
||||
id: '3',
|
||||
name: '开票',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
loadConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
|
@ -220,43 +335,83 @@
|
|||
|
||||
//
|
||||
clickItem(data) {
|
||||
console.log(data)
|
||||
if (data.id == 2) {
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
content: '确定要作废发票吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(data.id)
|
||||
this.deleteDepartment(this.list2[data.index].id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
this.editpart(this.list2[data.index])
|
||||
} else if (data.id == 4) {
|
||||
uni.showModal({
|
||||
content: '确定要反作废发票吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment1(this.list2[data.index].id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} else if (data.id == 3) {
|
||||
this.editpart(this.list2[data.index], '3')
|
||||
} else {
|
||||
this.editpart(this.list2[data.index], '1')
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
//删除
|
||||
//作废
|
||||
async deleteDepartment(id) {
|
||||
|
||||
const res = await deleteproject_task({
|
||||
const res = await tovoid({
|
||||
id: id
|
||||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.loadConfig.status = "loading"
|
||||
|
||||
if (this.num == 0) {
|
||||
this.initList()
|
||||
} else if (this.num == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
},
|
||||
//编辑项目
|
||||
editpart(item) {
|
||||
//反作废
|
||||
async deleteDepartment1(id) {
|
||||
|
||||
const res = await novoid({
|
||||
id: id
|
||||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
|
||||
if (this.num == 0) {
|
||||
this.initList()
|
||||
} else if (this.num == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
},
|
||||
|
||||
//编辑发票
|
||||
editpart(item, type) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/invoice/bianji??type=' + item.type
|
||||
url: '/pages/addfinanceincome/index??type=' + type + "&data=" + encodeURIComponent(JSON
|
||||
.stringify(
|
||||
item))
|
||||
})
|
||||
},
|
||||
tian(item) {
|
||||
|
@ -303,6 +458,7 @@
|
|||
|
||||
.content-middle {
|
||||
.content-middle-one {
|
||||
|
||||
.middle-one {
|
||||
width: 694rpx;
|
||||
|
||||
|
@ -311,6 +467,7 @@
|
|||
background: #FFFFFF;
|
||||
padding: 0 25rpx;
|
||||
|
||||
|
||||
padding-bottom: 25rpx;
|
||||
|
||||
.middle-edit {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<view class="middle-oneb">
|
||||
<view class="middle-oneb-a">
|
||||
<view class="threeb-a-a">
|
||||
<image :src="items.img" mode=""></image>
|
||||
<image src="@/static/images/gw.png" mode=""></image>
|
||||
</view>
|
||||
<view class="threeb-a-b">
|
||||
<view class="name"> <text>{{items.title}}</text></view>
|
||||
|
@ -80,7 +80,7 @@
|
|||
};
|
||||
},
|
||||
onShow() {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
},
|
||||
onReachBottom() {
|
||||
this.getDocumentList()
|
||||
|
@ -89,10 +89,16 @@
|
|||
uni.stopPullDownRefresh()
|
||||
},
|
||||
methods: {
|
||||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list = [];
|
||||
await this.getDocumentList();
|
||||
},
|
||||
//获取人事调动
|
||||
async getDocumentList() {
|
||||
|
||||
try {
|
||||
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
let res = await userposition({
|
||||
|
@ -108,9 +114,7 @@
|
|||
this.loadConfig.page++;
|
||||
}
|
||||
this.list = [...this.list, ...res?.data]
|
||||
} catch (e) {
|
||||
this.loadConfig.status = "nomore"
|
||||
}
|
||||
|
||||
},
|
||||
//添加岗位
|
||||
adddepart() {
|
||||
|
@ -140,7 +144,7 @@
|
|||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
|
@ -196,7 +200,7 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
margin-bottom: 25rpx;
|
||||
|
||||
.middle-oneb-a {
|
||||
display: flex;
|
||||
|
@ -242,7 +246,7 @@
|
|||
.middle-oneb-b {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-top: 45rpx;
|
||||
|
||||
|
||||
|
||||
image {
|
||||
|
|
|
@ -12,13 +12,14 @@
|
|||
<view class="leava_type flex_a_c"
|
||||
v-if="fieldValue.type=='select'&& fieldKey!='copy_uids'&&fieldKey!='check_admin_ids'&&fieldKey!='flow_id'&&fieldKey!='name'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixin(fieldKey)"
|
||||
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixin(fieldKey)"
|
||||
v-if="fieldKey!='name'">
|
||||
</view>
|
||||
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'">
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&fieldValue.type=='select'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixiner()">
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixiner()">
|
||||
</view>
|
||||
<view class=""
|
||||
v-if="fieldValue.type=='input'&&fieldKey!='end_time'&&fieldKey!='start_time'&&fieldKey!='duration'">
|
||||
|
@ -31,21 +32,31 @@
|
|||
<view class="" v-if=" fieldKey=='start_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[0].title }}</view>
|
||||
<input type="text" v-model="timeData[0].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[0])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime1">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='end_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[1].title }}</view>
|
||||
<input type="text" v-model="timeData[1].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[1])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime2">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='detail_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime3(fieldKey)">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<view class="" v-if="fieldKey=='duration'">
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
|
@ -127,7 +138,7 @@
|
|||
@confirm="leavaType">
|
||||
</u-picker> -->
|
||||
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择工作类别"
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择"
|
||||
@close="leavaTypeShow = false" @select="leavaType">
|
||||
|
||||
</u-action-sheet>
|
||||
|
@ -138,13 +149,13 @@
|
|||
|
||||
<!-- 审核人 -->
|
||||
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns"
|
||||
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" @close="branchShowclose"
|
||||
keyName="name">
|
||||
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" keyName="name"
|
||||
@close="branchShow = false" @cancel="branchShow = false">
|
||||
</u-picker>
|
||||
|
||||
<u-picker :show="branchShow1" :defaultIndex='defaultIndex1' ref="branchRef" :columns="branchColumns1"
|
||||
@confirm="branchConfirm1" @change="columnCode1" :closeOnClickOverlay="true" @close="branchShowclose1"
|
||||
keyName="name">
|
||||
@confirm="branchConfirm1" @change="columnCode1" :closeOnClickOverlay="true" @close="branchShow1 = false"
|
||||
@cancel="branchShow1 = false" keyName="name">
|
||||
</u-picker>
|
||||
<u-picker :show="branchShow2" :defaultIndex='defaultIndex2' ref="branchRef" :columns="branchColumns2"
|
||||
@confirm="branchConfirm2" @change="columnCode2" :closeOnClickOverlay="true" @close="branchShowclose2"
|
||||
|
@ -156,11 +167,14 @@
|
|||
@close="flag1 = false" @confirm="confirm" keyName="title" :defaultIndex=[0,0]>
|
||||
</u-picker>
|
||||
<!-- 选择时间 -->
|
||||
<block v-for="(item,i) in timeData" :key="i">
|
||||
<u-datetime-picker :show="item.timeShow" v-model="item.timeVal" mode="datetime" :maxDate="1786778555000"
|
||||
:minDate="timestamp" closeOnClickOverlay @confirm="timeConfirm($event,i)"
|
||||
@cancel="item.timeShow = false" @close="item.timeShow = false"></u-datetime-picker>
|
||||
</block>
|
||||
<u-datetime-picker :show="timeShow1" mode="datetime" :maxDate="1786778555000" closeOnClickOverlay
|
||||
@confirm="timeConfirm1($event)" @cancel="timeShow1 = false" @close="timeShow1 = false"></u-datetime-picker>
|
||||
|
||||
<u-datetime-picker :show="timeShow2" mode="datetime" :maxDate="1786778555000" closeOnClickOverlay
|
||||
@confirm="timeConfirm2($event)" @cancel="timeShow2 = false" @close="timeShow2 = false"></u-datetime-picker>
|
||||
<u-datetime-picker :show="timeShow" mode="datetime" :maxDate="1786778555000" :minDate="timestamp"
|
||||
closeOnClickOverlay @confirm="timeConfirm3($event)" @cancel="timeShow = false"
|
||||
@close="timeShow = false"></u-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
@ -207,7 +221,9 @@
|
|||
content: '', // 请假事由
|
||||
flowPathShow: false,
|
||||
flowPathSheet: [],
|
||||
|
||||
timeShow: false,
|
||||
timeShow1: false,
|
||||
timeShow2: false,
|
||||
timeData: [{
|
||||
title: '开始时间:',
|
||||
timeShow: false,
|
||||
|
@ -259,7 +275,6 @@
|
|||
token: this.$store.state.app.token
|
||||
}
|
||||
},
|
||||
|
||||
this.typeId = option.type
|
||||
if (option.type == 8) {
|
||||
this.timeData[0].title = '借用日期:'
|
||||
|
@ -329,71 +344,98 @@
|
|||
})
|
||||
|
||||
this.dataobj = res.data.field
|
||||
console.log(this.columns)
|
||||
this.meatelist.type= this.dataobj1.detail.type
|
||||
|
||||
if ('name' in res.data.field) {
|
||||
this.meatelist.name = 'name' in this.dataobj1.detail ? this.dataobj1.detail.name : ''
|
||||
if (this.typeId != 53) {
|
||||
this.timeData[0].time = 'start_time' in this.dataobj1.detail ? this.dataobj1.detail.start_time : ''
|
||||
this.timeData[1].time = 'end_time' in this.dataobj1.detail ? this.dataobj1.detail.end_time : ''
|
||||
}
|
||||
if ('start_time' in res.data.field) {
|
||||
this.meatelist.start_time = 'start_time' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
.start_time : ''
|
||||
}
|
||||
|
||||
if ('end_time' in res.data.field) {
|
||||
this.meatelist.end_time = 'end_time' in this.dataobj1.detail ? this.dataobj1.detail.end_time : ''
|
||||
}
|
||||
|
||||
if ('mobile' in res.data.field) {
|
||||
this.meatelist.mobile = 'mobile' in this.dataobj1.detail ? this.dataobj1.detail.mobile : ''
|
||||
// this.meatelist.department_type = 'department_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .department_type_title : ''
|
||||
// this.meatelist.detail_type = 'detail_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .detail_type_title : ''
|
||||
// this.meatelist.other_type = 'other_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .other_type_title : ''
|
||||
|
||||
}
|
||||
if ('remark' in res.data.field) {
|
||||
this.meatelist.remark = 'remark' in this.dataobj1.detail ? this.dataobj1.detail.remark : ''
|
||||
}
|
||||
if ('remark1' in res.data.field) {
|
||||
this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
}
|
||||
if ( 'address' in res.data.field) {
|
||||
this.meatelist.address = 'address' in this.dataobj1.detail ? this.dataobj1.detail.address : ''
|
||||
this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail.detail_time :
|
||||
''
|
||||
}
|
||||
if ('detail_time' in res.data.field) {
|
||||
|
||||
this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
.detail_time :
|
||||
''
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ('content' in res.data.field) {
|
||||
|
||||
this.meatelist.content = 'content' in this.dataobj1.detail ? this.dataobj1.detail.content : ''
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// this.check_admin_name = 'check_user' in this.dataobj1.detail ? this.dataobj1.detail.check_user : ''
|
||||
// this.check_admin_ids = 'check_admin_ids' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .check_admin_ids : ''
|
||||
// this.copy_uids = 'copy_uids' in this.dataobj1.detail ? this.dataobj1.detail.copy_uids : ''
|
||||
// this.copy_names = 'copy_user' in this.dataobj1.detail ? this.dataobj1.detail.copy_user : ''
|
||||
this.flowPath = 'file_ids_title' in this.dataobj1.detail ? this.dataobj1.detail.file_ids_title : ''
|
||||
this.flow_id = 'flow_id' in this.dataobj1.detail ? this.dataobj1.detail.flow_id : ''
|
||||
// this.flowPath = 'file_ids_title' in this.dataobj1.detail ? this.dataobj1.detail.file_ids_title : ''
|
||||
// this.flow_id = 'flow_id' in this.dataobj1.detail ? this.dataobj1.detail.flow_id : ''
|
||||
// console.log('num' in res.data.field)
|
||||
|
||||
|
||||
if ('num' in res.data.field) {
|
||||
this.meatelist.num = 'num' in this.dataobj1.detail ? this.dataobj1.detail.num : ''
|
||||
}
|
||||
if ('num1' in res.data.field) {
|
||||
this.meatelist.num1 = 'num1' in this.dataobj1.detail ? this.dataobj1.detail.num1 : ''
|
||||
}
|
||||
if ('amount' in res.data.field) {
|
||||
this.meatelist.amount = 'amount' in this.dataobj1.detail ? this.dataobj1.detail.amount : ''
|
||||
}
|
||||
if ('bank' in res.data.field) {
|
||||
this.meatelist.bank = 'bank' in this.dataobj1.detail ? this.dataobj1.detail.bank : ''
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if ('flow_id' in res.data.field) {
|
||||
const detailTypeOptions1 = Object.entries(res.data.field.flow_id.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
}));
|
||||
|
||||
// console.log(detailTypeOptions1)
|
||||
this.flowPathSheet = detailTypeOptions1
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ('fileArray' in this.dataobj1.detail) {
|
||||
this.fileArray = res.data.detail.fileArray.map(function(obj) {
|
||||
if (this.dataobj1 && this.dataobj1.detail && this.dataobj1.detail.fileArray) {
|
||||
this.fileArray = this.dataobj1.detail.fileArray.map(function(obj) {
|
||||
return {
|
||||
name: obj.name,
|
||||
filesize: obj.filesize
|
||||
};
|
||||
});
|
||||
}
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// console.log(this.timeData)
|
||||
|
||||
|
||||
|
||||
if ('detail_type' in this.dataobj) {
|
||||
if ('detail_type' in res.data.field) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.detail_type.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
|
@ -401,7 +443,7 @@
|
|||
this.columns = detailTypeOptions
|
||||
|
||||
for (let i in this.columns) {
|
||||
console.log(this.columns[i].id, this.dataobj1.detail.detail_type, '1111111111111')
|
||||
|
||||
if (this.columns[i].id == this.dataobj1.detail.detail_type) {
|
||||
this.meatelist.detail_type = this.columns[i].name
|
||||
this.leavaTypeId1 = this.columns[i].id
|
||||
|
@ -413,7 +455,7 @@
|
|||
|
||||
}
|
||||
|
||||
if ('department_type' in this.dataobj) {
|
||||
if ('department_type' in res.data.field) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.department_type.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
|
@ -432,7 +474,7 @@
|
|||
|
||||
}
|
||||
|
||||
if ('other_type' in this.dataobj) {
|
||||
if ('other_type' in res.data.field) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.other_type.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
|
@ -451,7 +493,7 @@
|
|||
|
||||
}
|
||||
|
||||
if ('position_type' in this.dataobj) {
|
||||
if ('position_type' in res.data.field) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.position_type.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
|
@ -643,8 +685,15 @@
|
|||
branchShowclose2() {
|
||||
this.branchShow2 = false
|
||||
},
|
||||
selectTime(item) {
|
||||
item.timeShow = true
|
||||
selectTime1(item) {
|
||||
this.timeShow1 = true
|
||||
|
||||
},
|
||||
selectTime2(item) {
|
||||
this.timeShow2 = true
|
||||
},
|
||||
selectTime3(item) {
|
||||
this.timeShow = true
|
||||
},
|
||||
async branchHandler(e) {
|
||||
const {
|
||||
|
@ -725,17 +774,25 @@
|
|||
|
||||
},
|
||||
|
||||
timeConfirm(e, i) {
|
||||
this.timeData[i].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
// this.timeData[i].timeDay = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
// this.timeData[i].timeHour = uni.$u.timeFormat(e.value, 'hh:MM')
|
||||
this.timeData[i].timeShow = false
|
||||
timeConfirm1(e, i) {
|
||||
this.meatelist.start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeData[0].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeShow1 = false
|
||||
},
|
||||
timeConfirm2(e, i) {
|
||||
this.meatelist.end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeData[1].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeShow2 = false
|
||||
},
|
||||
timeConfirm3(e, i) {
|
||||
this.meatelist.detail_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.timeShow = false
|
||||
},
|
||||
async submiteBtn() {
|
||||
console.log(this.leavaTypeId2)
|
||||
let subData;
|
||||
let subData1;
|
||||
if (this.typeId == 6 || this.typeId == 7 || this.typeId == 8 || this.typeId == 21) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -744,7 +801,6 @@
|
|||
fileIds.push(item.id)
|
||||
});
|
||||
subData1 = {
|
||||
detail_type: this.leavaTypeId1,
|
||||
content: this.meatelist.content,
|
||||
check_admin_name: this.check_admin_name,
|
||||
check_admin_ids: this.check_admin_ids,
|
||||
|
@ -752,55 +808,38 @@
|
|||
file_ids: fileIds.join(','),
|
||||
copy_names: this.copy_names,
|
||||
copy_uids: this.copy_uids,
|
||||
type: this.typeId,
|
||||
|
||||
}
|
||||
|
||||
if (this.typeId == 8) {
|
||||
subData1.start_time = this.timeData[0].time,
|
||||
subData1.end_time = this.timeData[1].time,
|
||||
|
||||
|
||||
if (this.meatelist.hasOwnProperty('department_type')) {
|
||||
subData1.department_type = this.leavaTypeId
|
||||
subData1.detail_type = this.leavaTypeId1
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('other_type')) {
|
||||
subData1.other_type = this.leavaTypeId2
|
||||
|
||||
}
|
||||
if (this.typeId == 21) {
|
||||
subData1.department_type = this.leavaTypeId
|
||||
if (this.meatelist.hasOwnProperty('position_type')) {
|
||||
subData1.position_type = this.leavaTypeId3
|
||||
// console.log(subData1.position_type , this.leavaTypeId3)
|
||||
}
|
||||
console.log(this.meatelist.hasOwnProperty('detail_type'))
|
||||
if (this.meatelist.hasOwnProperty('detail_type')) {
|
||||
subData1.detail_type = this.leavaTypeId1
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('num') && this.typeId == 20) {
|
||||
subData1.num = this.leavaTypeId4
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('num1') && this.typeId == 20) {
|
||||
subData1.num1 = this.leavaTypeId5
|
||||
}
|
||||
|
||||
|
||||
subData = {
|
||||
...this.meatelist,
|
||||
...subData1
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
let fileIds = [];
|
||||
this.fileArray.map((item, i) => {
|
||||
fileIds.push(item.id)
|
||||
});
|
||||
|
||||
subData = {
|
||||
detail_type: this.leavaTypeId1,
|
||||
start_time: this.timeData[0].time,
|
||||
end_time: this.timeData[1].time,
|
||||
duration: this.manHour,
|
||||
content: this.meatelist.content,
|
||||
check_admin_name: this.check_admin_name,
|
||||
check_admin_ids: this.check_admin_ids,
|
||||
flow_id: this.flow_id,
|
||||
file_ids: fileIds.join(','),
|
||||
copy_names: this.copy_names,
|
||||
copy_uids: this.copy_uids,
|
||||
type: this.typeId,
|
||||
file: ''
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -947,7 +986,10 @@
|
|||
position: relative;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
/deep/.u-action-sheet__item-wrap {
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.leave_box,
|
||||
.flow_path {
|
||||
width: 100%;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixin(fieldKey)">
|
||||
|
||||
</view>
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&&typeId!=24">
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&fieldValue.type=='select'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixiner()">
|
||||
</view>
|
||||
|
@ -30,18 +30,27 @@
|
|||
<view class="" v-if=" fieldKey=='start_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[0].title }}</view>
|
||||
<input type="text" v-model="timeData[0].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[0])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='end_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[1].title }}</view>
|
||||
<input type="text" v-model="timeData[1].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[1])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='detail_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime3(fieldKey)">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
@ -89,11 +98,17 @@
|
|||
|
||||
|
||||
|
||||
</view>
|
||||
<view class="" style="background-color: #fff;margin-bottom: 30rpx;">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="ktype!=0 &&dataobj1.detail.check_status!=2">
|
||||
<view class="title" style="width: 200rpx;">撤回意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入撤回意见" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cont_details">
|
||||
|
||||
<view class="examine">审批流程</view>
|
||||
<view class="cont_cell"
|
||||
v-if="dataobj1 && dataobj1.detail && dataobj1.detail.hasOwnProperty('check_status')">
|
||||
<view class="cont_cell">
|
||||
<view class="title">审核状态:</view>
|
||||
|
||||
{{dataobj1.detail.check_status=='0'?'待审核':dataobj1.detail.check_status=='1'?'审核中':dataobj1.detail.check_status=='2'?'审核通过':dataobj1.detail.check_status=='3'?'审核不通过':'撤销审核'}}
|
||||
|
@ -115,13 +130,11 @@
|
|||
了此申请。操作意见:{{item.content}}</text>
|
||||
</view>
|
||||
</block>
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="ktype!=0">
|
||||
<view class="title" style="width: 200rpx;">撤回意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入撤回意见" />
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
<view class="" v-if="ktype!=0">
|
||||
<view class="" v-if="ktype!=0&&dataobj1.detail.check_status!=2">
|
||||
<view class="bot_btn" v-if='dataobj1.detail.check_status!=4'>
|
||||
<!-- <view class="reset" @click="appflowcheck()">拒绝</view>
|
||||
<view class="submit_btn" @click=" appflowcheck1()">通过</view> -->
|
||||
|
@ -295,24 +308,25 @@
|
|||
})
|
||||
|
||||
this.dataobj = res.data.field
|
||||
this.meatelist.name = 'name' in this.dataobj1.detail ? this.dataobj1.detail.name : ''
|
||||
this.timeData[0].time = 'start_time' in this.dataobj1.detail ? this.dataobj1.detail.start_time : ''
|
||||
this.timeData[1].time = 'end_time' in this.dataobj1.detail ? this.dataobj1.detail.end_time : ''
|
||||
this.meatelist.mobile = 'mobile' in this.dataobj1.detail ? this.dataobj1.detail.mobile : ''
|
||||
this.meatelist.department_type = 'department_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
.department_type_title : ''
|
||||
this.meatelist.detail_type = 'detail_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
.detail_type_title : ''
|
||||
this.meatelist.other_type = 'other_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
.other_type_title : ''
|
||||
this.meatelist.remark = 'remark' in this.dataobj1.detail ? this.dataobj1.detail.remark : ''
|
||||
this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
this.meatelist.address = 'address' in this.dataobj1.detail ? this.dataobj1.detail.address : ''
|
||||
this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail.detail_time :
|
||||
''
|
||||
this.meatelist.content = 'content' in this.dataobj1.detail ? this.dataobj1.detail.content : ''
|
||||
this.meatelist.num = 'num' in this.dataobj1.detail ? this.dataobj1.detail.num : ''
|
||||
|
||||
this.meatelist=this.dataobj1.detail
|
||||
// this.meatelist.name = 'name' in this.dataobj1.detail ? this.dataobj1.detail.name : ''
|
||||
// this.timeData[0].time = 'start_time' in this.dataobj1.detail ? this.dataobj1.detail.start_time : ''
|
||||
// this.timeData[1].time = 'end_time' in this.dataobj1.detail ? this.dataobj1.detail.end_time : ''
|
||||
// this.meatelist.mobile = 'mobile' in this.dataobj1.detail ? this.dataobj1.detail.mobile : ''
|
||||
// this.meatelist.department_type = 'department_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .department_type_title : ''
|
||||
// this.meatelist.detail_type = 'detail_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .detail_type_title : ''
|
||||
// this.meatelist.other_type = 'other_type' in this.dataobj1.detail ? this.dataobj1.detail
|
||||
// .other_type_title : ''
|
||||
// this.meatelist.remark = 'remark' in this.dataobj1.detail ? this.dataobj1.detail.remark : ''
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
// this.meatelist.address = 'address' in this.dataobj1.detail ? this.dataobj1.detail.address : ''
|
||||
// this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail.detail_time :
|
||||
// ''
|
||||
// this.meatelist.content = 'content' in this.dataobj1.detail ? this.dataobj1.detail.content : ''
|
||||
// this.meatelist.num = 'num' in this.dataobj1.detail ? this.dataobj1.detail.num : ''
|
||||
// this.meatelist.num1 = 'num1' in this.dataobj1.detail ? this.dataobj1.detail.num1 : ''
|
||||
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
|
@ -325,7 +339,7 @@
|
|||
|
||||
// console.log(this.meatelist.detail_type, '2222222222')
|
||||
|
||||
console.log(this.dataobj1.detail.detail_type)
|
||||
// console.log(this.dataobj1.detail.detail_type)
|
||||
|
||||
if ('detail_type' in this.dataobj) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.detail_type.item).map(([id, name]) => ({
|
||||
|
@ -340,7 +354,7 @@
|
|||
this.meatelist.detail_type = this.columns[i].name
|
||||
this.leavaTypeId1 = this.columns[i].id
|
||||
}
|
||||
console.log(this.meatelist.detail_type, this.leavaTypeId1)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -402,13 +416,15 @@
|
|||
|
||||
|
||||
}
|
||||
|
||||
if (this.dataobj1 && this.dataobj1.detail && this.dataobj1.detail.fileArray) {
|
||||
this.fileArray = this.dataobj1.detail.fileArray.map(function(obj) {
|
||||
return {
|
||||
name: obj.name,
|
||||
filesize: obj.filesize
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<view class="leave_request">
|
||||
|
||||
<view class="leave_box">
|
||||
|
||||
|
||||
|
@ -11,12 +12,12 @@
|
|||
v-if="fieldValue.type=='select'&&fieldKey!='copy_uids'&&fieldKey!='check_admin_ids'&&fieldKey!='flow_id'&&fieldKey!='name'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<!-- {{fieldKey}} -->
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixin(fieldKey)">
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixin(fieldKey)">
|
||||
|
||||
</view>
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&&typeId!=24">
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&fieldValue.type=='select'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixiner()">
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixiner()">
|
||||
</view>
|
||||
|
||||
<view class=""
|
||||
|
@ -44,6 +45,15 @@
|
|||
@click="selectTime(timeData[1])">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='detail_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime3(fieldKey)">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='duration'">
|
||||
<view class="cont_cell">
|
||||
|
@ -71,42 +81,36 @@
|
|||
<u-icon @click="delImg(i)" name="close-circle" color="#333333" size="28"></u-icon>
|
||||
</view>
|
||||
</block>
|
||||
<!-- <view class="upload_box flex_a_c_j_sb" @click="seleckImage">
|
||||
<view>
|
||||
<view class="title">选择文件并上传</view>
|
||||
<view class="text">
|
||||
上传前,请规范命名,最大只能上传100M的文件<br />
|
||||
超过请压缩成多个文件上传。
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<u-icon name="plus-circle" color="#333333" size="28"></u-icon>
|
||||
</view> -->
|
||||
</view>
|
||||
<!-- <view class="" v-for="(itemValue, itemKey) in fieldValue.item" :key="itemKey">
|
||||
{{ itemKey }}: {{ itemValue }}
|
||||
</view> -->
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
</view>
|
||||
<view class="cont_details">
|
||||
<view class="examine">审批流程</view>
|
||||
|
||||
|
||||
<view class="flow_path">
|
||||
<view class="">
|
||||
<view class="cont_cell">
|
||||
<view class="title">审批流程:</view>
|
||||
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">审核状态:</view>
|
||||
|
||||
{{dataobj1.detail.check_status=='0'?'待审核':dataobj1.detail.check_status=='1'?'审核中':dataobj1.detail.check_status=='2'?'审核通过':dataobj1.detail.check_status=='3'?'审核不通过':'撤销审核'}}
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">当前审核人:</view>
|
||||
<input type="text" v-model="dataobj1.detail.check_user" disabled placeholder="请假工时">
|
||||
<view class="title">审核人:</view>
|
||||
<input type="text" v-model="dataobj1.detail.check_user" placeholder="请选择" disabled>
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">抄送人:</view>
|
||||
<input type="text" v-model="dataobj1.detail.copy_user" disabled placeholder="请假工时">
|
||||
<input type="text" v-model="dataobj1.detail.copy_user" placeholder="请选择" disabled>
|
||||
</view>
|
||||
|
||||
<view class="examine">审批记录</view>
|
||||
<block v-for="(item,i) in check_record" :key="i">
|
||||
<view class="record" style="display: flex;">
|
||||
<view class="circle"></view>
|
||||
|
@ -114,9 +118,11 @@
|
|||
了此申请。操作意见:{{item.content}}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<view class="flow_path">
|
||||
|
||||
|
||||
</view>
|
||||
<view class="" v-if="dataobj1.detail.check_status!=2">
|
||||
<radio-group class="select_group" @change="deliveryWayChangetwo">
|
||||
<label class="radio_select" style="margin-right:15rpx;display: flex; margin-bottom: 30rpx;">
|
||||
<view style="margin-right:5rpx;">
|
||||
|
@ -128,37 +134,39 @@
|
|||
<view style="margin-right:5rpx;">
|
||||
<radio value="2" />
|
||||
</view>
|
||||
<view @click="branchShow = true" style="display: flex;">
|
||||
<view class="cont_cell" style="margin-top: -25rpx;">
|
||||
<view class="title"> 下一位审批人:</view>
|
||||
<input type="text" v-model="check_admin_name" placeholder="请选择" disabled>
|
||||
<input type="text" @click="leixiner1" v-model="check_admin_name" placeholder="请选择" disabled>
|
||||
</view>
|
||||
</label>
|
||||
</radio-group>
|
||||
|
||||
<!-- <view class="cont_cell" @click="branchShow1 = true">
|
||||
<view class="title">抄送人:</view>
|
||||
<input type="text" v-model="copy_names" placeholder="请选择" disabled>
|
||||
</view> -->
|
||||
<view class="cont_cell" style="padding-top: 20rpx;">
|
||||
|
||||
</view>
|
||||
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="dataobj1.detail.check_status!=2">
|
||||
<view class="title" style="width: 200rpx;">审核意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入审核意见" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bot_btn">
|
||||
<view class="bot_btn" v-if="dataobj1.detail.check_status!=2">
|
||||
<view class="reset" @click="appflowcheck()">拒绝</view>
|
||||
<view class="submit_btn" @click="appflowcheck1()">通过</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
|
||||
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns"
|
||||
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" @close="branchShowclose"
|
||||
keyName="name">
|
||||
@cancel='branchShowclose' @confirm="branchConfirm" @change="columnCode" closeOnClickOverlay
|
||||
@close="branchShowclose" keyName="name">
|
||||
</u-picker>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
oaUploads
|
||||
} from '../../api/upload'
|
||||
|
@ -248,6 +256,7 @@
|
|||
this.applist(option.type)
|
||||
this.getDocumentList()
|
||||
this.getDocumentList2()
|
||||
|
||||
},
|
||||
onShow() {
|
||||
// this.getFlow()
|
||||
|
@ -327,7 +336,10 @@
|
|||
this.meatelist.detail_time = 'detail_time' in this.dataobj1.detail ? this.dataobj1.detail.detail_time :
|
||||
''
|
||||
this.meatelist.content = 'content' in this.dataobj1.detail ? this.dataobj1.detail.content : ''
|
||||
|
||||
this.meatelist.num = 'num' in this.dataobj1.detail ? this.dataobj1.detail.num : ''
|
||||
this.meatelist.num1 = 'num1' in this.dataobj1.detail ? this.dataobj1.detail.num1 : ''
|
||||
this.meatelist.amount = 'amount' in this.dataobj1.detail ? this.dataobj1.detail.amount : ''
|
||||
this.meatelist.bank = 'bank' in this.dataobj1.detail ? this.dataobj1.detail.bank : ''
|
||||
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
// this.meatelist.remark1 = 'remark1' in this.dataobj1.detail ? this.dataobj1.detail.remark1 : ''
|
||||
|
@ -355,7 +367,7 @@
|
|||
this.meatelist.detail_type = this.columns[i].name
|
||||
this.leavaTypeId1 = this.columns[i].id
|
||||
}
|
||||
console.log(this.meatelist.detail_type,this.leavaTypeId1)
|
||||
// console.log(this.meatelist.detail_type,this.leavaTypeId1)
|
||||
}
|
||||
|
||||
|
||||
|
@ -418,6 +430,43 @@
|
|||
|
||||
}
|
||||
|
||||
if ('num' in this.dataobj && this.dataobj1.detail.type == 20) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.num.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
}));
|
||||
this.columns = detailTypeOptions
|
||||
|
||||
for (let i in this.columns) {
|
||||
|
||||
if (this.columns[i].id == this.dataobj1.detail.num) {
|
||||
this.meatelist.num = this.columns[i].name
|
||||
this.leavaTypeId4 = this.columns[i].id
|
||||
}
|
||||
// console.log(this.meatelist.detail_type)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ('num1' in this.dataobj && this.dataobj1.detail.type == 20) {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.num1.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
}));
|
||||
this.columns = detailTypeOptions
|
||||
|
||||
for (let i in this.columns) {
|
||||
|
||||
if (this.columns[i].id == this.dataobj1.detail.num1) {
|
||||
this.meatelist.num1 = this.columns[i].name
|
||||
this.leavaTypeId5 = this.columns[i].id
|
||||
}
|
||||
// console.log(this.meatelist.detail_type)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
//获取部门
|
||||
|
@ -462,6 +511,8 @@
|
|||
this.branchColumns = codelist
|
||||
this.branchColumns1 = codelist
|
||||
this.branchColumns2 = codelist
|
||||
|
||||
console.log(this.branchColumns)
|
||||
})
|
||||
|
||||
|
||||
|
@ -541,7 +592,7 @@
|
|||
|
||||
//选择是否结束
|
||||
deliveryWayChangetwo(e) {
|
||||
console.log(e)
|
||||
// console.log(e)
|
||||
this.check = e.detail.value
|
||||
},
|
||||
//流程审批
|
||||
|
@ -555,7 +606,12 @@
|
|||
check_admin_ids: this.check_admin_ids.toString()
|
||||
}
|
||||
let res = await appflow_check(data)
|
||||
if (res.code == 0) {
|
||||
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
|
||||
Toast(res.msg)
|
||||
},
|
||||
|
@ -570,6 +626,12 @@
|
|||
}
|
||||
let res = await appflow_check(data)
|
||||
console.log(res)
|
||||
if (res.code == 0) {
|
||||
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
Toast(res.msg)
|
||||
},
|
||||
leixin(e) {
|
||||
|
@ -604,7 +666,12 @@
|
|||
leixiner() {
|
||||
this.branchShow2 = true
|
||||
},
|
||||
leixiner1() {
|
||||
this.branchShow = true
|
||||
console.log('111111111', this.branchShow)
|
||||
},
|
||||
branchShowclose() {
|
||||
|
||||
this.branchShow = false
|
||||
},
|
||||
branchShowclose1() {
|
||||
|
@ -613,29 +680,7 @@
|
|||
selectTime(item) {
|
||||
item.timeShow = true
|
||||
},
|
||||
async branchHandler(e) {
|
||||
const {
|
||||
columnIndex,
|
||||
value,
|
||||
values, // values为当前变化列的数组内容
|
||||
index,
|
||||
// 微信小程序无法将picker实例传出来,只能通过ref操作
|
||||
picker = this.$refs.branchRef
|
||||
} = e
|
||||
// 当第一列值发生变化时,变化第二列(后一列)对应的选项
|
||||
if (columnIndex === 0) {
|
||||
// picker为选择器this实例,变化第二列对应的选项
|
||||
let res = await getEmployeeAPI({
|
||||
did: value[0].id
|
||||
})
|
||||
if (res.length < 1) {
|
||||
res[0] = {
|
||||
name: '无'
|
||||
}
|
||||
}
|
||||
picker.setColumnValues(1, res)
|
||||
}
|
||||
},
|
||||
|
||||
// 回调参数为包含columnIndex、value、values
|
||||
branchConfirm(e) {
|
||||
console.log('confirm', e, e.value[2].name)
|
||||
|
@ -772,6 +817,11 @@
|
|||
|
||||
try {
|
||||
const res = await appapprove(subData)
|
||||
if (res.code == 0) {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
}
|
||||
Toast('提交成功')
|
||||
} catch (e) {
|
||||
Toast('提交失败')
|
||||
|
@ -837,7 +887,10 @@
|
|||
position: relative;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
/deep/.u-action-sheet__item-wrap {
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.leave_box,
|
||||
.flow_path {
|
||||
width: 100%;
|
||||
|
@ -961,6 +1014,7 @@
|
|||
margin: 31.58rpx;
|
||||
}
|
||||
}
|
||||
|
||||
:last-child {
|
||||
.circle {
|
||||
&::before {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,13 +15,14 @@
|
|||
<view class="leava_type flex_a_c"
|
||||
v-if="fieldValue.type=='select'&& fieldKey!='copy_uids'&&fieldKey!='check_admin_ids'&&fieldKey!='flow_id'&&fieldKey!='name'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixin(fieldKey)"
|
||||
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixin(fieldKey)"
|
||||
v-if="fieldKey!='name'">
|
||||
</view>
|
||||
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&typeId!=6">
|
||||
<view class="leava_type flex_a_c" v-if="fieldKey=='name'&fieldValue.type=='select'">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" @click="leixiner()">
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择" disabled @click="leixiner()">
|
||||
</view>
|
||||
<view class=""
|
||||
v-if="fieldValue.type=='input'&&fieldKey!='end_time'&&fieldKey!='start_time'&&fieldKey!='duration'">
|
||||
|
@ -34,21 +35,32 @@
|
|||
<view class="" v-if=" fieldKey=='start_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[0].title }}</view>
|
||||
<input type="text" v-model="timeData[0].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[0])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime1">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='end_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ timeData[1].title }}</view>
|
||||
<input type="text" v-model="timeData[1].time" placeholder="请选择时间" disabled
|
||||
@click="selectTime(timeData[1])">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime2">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="" v-if="fieldKey=='detail_time'">
|
||||
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
<input type="text" v-model="meatelist[fieldKey]" placeholder="请选择时间" disabled
|
||||
@click="selectTime3(fieldKey)">
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<view class="" v-if="fieldKey=='duration'">
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{fieldValue.title}}:</view>
|
||||
|
@ -130,7 +142,7 @@
|
|||
@confirm="leavaType">
|
||||
</u-picker> -->
|
||||
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择工作类别"
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择类别"
|
||||
@close="leavaTypeShow = false" @select="leavaType">
|
||||
|
||||
</u-action-sheet>
|
||||
|
@ -142,33 +154,39 @@
|
|||
<!-- 审核人 -->
|
||||
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns"
|
||||
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" @close="branchShowclose"
|
||||
keyName="name">
|
||||
keyName="name" @cancel="branchShowclose">
|
||||
</u-picker>
|
||||
|
||||
<u-picker :show="branchShow1" :defaultIndex='defaultIndex1' ref="branchRef" :columns="branchColumns1"
|
||||
@confirm="branchConfirm1" @change="columnCode1" :closeOnClickOverlay="true" @close="branchShowclose1"
|
||||
keyName="name">
|
||||
@cancel="branchShowclose1" keyName="name">
|
||||
</u-picker>
|
||||
<u-picker :show="branchShow2" :defaultIndex='defaultIndex2' ref="branchRef" :columns="branchColumns2"
|
||||
@confirm="branchConfirm2" @change="columnCode2" :closeOnClickOverlay="true" @close="branchShowclose2"
|
||||
keyName="name">
|
||||
@cancel="branchShowclose2" keyName="name">
|
||||
</u-picker>
|
||||
|
||||
|
||||
<u-picker :show="flag1" :columns="columns3" ref="uPicker4" @cancel="flag1 = false" closeOnClickOverlay
|
||||
@close="flag1 = false" @confirm="confirm" keyName="title" :defaultIndex=[0,0]>
|
||||
</u-picker>
|
||||
|
||||
<!-- 选择时间 -->
|
||||
<block v-for="(item,i) in timeData" :key="i">
|
||||
<u-datetime-picker :show="item.timeShow" v-model="item.timeVal" mode="datetime" :maxDate="1786778555000"
|
||||
:minDate="timestamp" closeOnClickOverlay @confirm="timeConfirm($event,i)"
|
||||
@cancel="item.timeShow = false" @close="item.timeShow = false"></u-datetime-picker>
|
||||
</block>
|
||||
|
||||
<u-datetime-picker :show="timeShow1" mode="datetime" :maxDate="1786778555000" closeOnClickOverlay
|
||||
@confirm="timeConfirm1($event)" @cancel="timeShow1 = false" @close="timeShow1 = false"></u-datetime-picker>
|
||||
|
||||
<u-datetime-picker :show="timeShow2" mode="datetime" :maxDate="1786778555000" closeOnClickOverlay
|
||||
@confirm="timeConfirm2($event)" @cancel="timeShow2 = false" @close="timeShow2 = false"></u-datetime-picker>
|
||||
<u-datetime-picker :show="timeShow" mode="datetime" :maxDate="1786778555000" :minDate="timestamp"
|
||||
closeOnClickOverlay @confirm="timeConfirm3($event)" @cancel="timeShow = false"
|
||||
@close="timeShow = false"></u-datetime-picker>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {
|
||||
oaUploads
|
||||
} from '../../api/upload'
|
||||
|
@ -211,7 +229,9 @@
|
|||
content: '', // 请假事由
|
||||
flowPathShow: false,
|
||||
flowPathSheet: [],
|
||||
|
||||
timeShow: false,
|
||||
timeShow1: false,
|
||||
timeShow2: false,
|
||||
timeData: [{
|
||||
title: '开始时间:',
|
||||
timeShow: false,
|
||||
|
@ -235,6 +255,8 @@
|
|||
leavaTypeId1: '',
|
||||
leavaTypeId2: '',
|
||||
leavaTypeId3: '',
|
||||
leavaTypeId4: '',
|
||||
leavaTypeId5: '',
|
||||
columns: [],
|
||||
// 部门选择 三级级联动
|
||||
branchShow: false,
|
||||
|
@ -265,10 +287,10 @@
|
|||
},
|
||||
|
||||
this.typeId = option.type
|
||||
if (option.type == 8) {
|
||||
this.timeData[0].title = '借用日期:'
|
||||
this.timeData[1].title = '拟归还日期:'
|
||||
}
|
||||
// if (option.type == 8) {
|
||||
// this.timeData[0].title = '借用日期:'
|
||||
// this.timeData[1].title = '拟归还日期:'
|
||||
// }
|
||||
this.applist(option.type)
|
||||
this.getDocumentList()
|
||||
this.getDocumentList2()
|
||||
|
@ -288,6 +310,7 @@
|
|||
leaveHours
|
||||
} = this.calculateLeaveDaysAndHours(this.timeData[0].time, this.timeData[1]
|
||||
.time)
|
||||
console.log(leaveHours, leaveDays)
|
||||
this.manHour = leaveHours + '小时'
|
||||
this.daysNum = leaveDays + '天'
|
||||
}
|
||||
|
@ -477,6 +500,20 @@
|
|||
this.columns = detailTypeOptions
|
||||
}
|
||||
|
||||
if (e == 'num') {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.num.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
}));
|
||||
this.columns = detailTypeOptions
|
||||
}
|
||||
if (e == 'num1') {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.num1.item).map(([id, name]) => ({
|
||||
id,
|
||||
name
|
||||
}));
|
||||
this.columns = detailTypeOptions
|
||||
}
|
||||
if (e == 'position_type') {
|
||||
const detailTypeOptions = Object.entries(this.dataobj.position_type.item).map(([id, name]) => ({
|
||||
id,
|
||||
|
@ -500,8 +537,15 @@
|
|||
branchShowclose2() {
|
||||
this.branchShow2 = false
|
||||
},
|
||||
selectTime(item) {
|
||||
item.timeShow = true
|
||||
selectTime1(item) {
|
||||
this.timeShow1 = true
|
||||
|
||||
},
|
||||
selectTime2(item) {
|
||||
this.timeShow2 = true
|
||||
},
|
||||
selectTime3(item) {
|
||||
this.timeShow = true
|
||||
},
|
||||
async branchHandler(e) {
|
||||
const {
|
||||
|
@ -563,6 +607,12 @@
|
|||
} else if (this.datatype == 'position_type') {
|
||||
this.meatelist.position_type = e.name
|
||||
this.leavaTypeId3 = e.id
|
||||
} else if (this.datatype == 'num') {
|
||||
this.meatelist.num = e.name
|
||||
this.leavaTypeId4 = e.id
|
||||
} else if (this.datatype == 'num1') {
|
||||
this.meatelist.num1 = e.name
|
||||
this.leavaTypeId5 = e.id
|
||||
}
|
||||
console.log(this.leavaTypeId2)
|
||||
// console.log(this.meatelist,this.datatype, e.name)
|
||||
|
@ -588,21 +638,29 @@
|
|||
})
|
||||
this.flowPathSheet = flow
|
||||
},
|
||||
timeConfirm(e, i) {
|
||||
this.timeData[i].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeData[i].timeDay = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.timeData[i].timeHour = uni.$u.timeFormat(e.value, 'hh:MM')
|
||||
this.timeData[i].timeShow = false
|
||||
timeConfirm1(e, i) {
|
||||
this.meatelist.start_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeData[0].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeShow1 = false
|
||||
},
|
||||
timeConfirm2(e, i) {
|
||||
this.meatelist.end_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeData[1].time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
|
||||
this.timeShow2 = false
|
||||
},
|
||||
timeConfirm3(e, i) {
|
||||
this.meatelist.detail_time = uni.$u.timeFormat(e.value, 'yyyy-mm-dd')
|
||||
this.timeShow = false
|
||||
},
|
||||
async submiteBtn() {
|
||||
console.log(this.leavaTypeId2)
|
||||
console.log(this.leavaTypeId2, this.meatelist)
|
||||
if (this.meatelist.mobile) {
|
||||
const pattern = /^1[3456789]\d{9}$/;
|
||||
if (!pattern.test(this.meatelist.mobile)) return Toast('手机号输入错误')
|
||||
}
|
||||
let subData;
|
||||
let subData1;
|
||||
if (this.typeId == 6 || this.typeId == 7 || this.typeId == 8 || this.typeId == 21) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -611,7 +669,6 @@
|
|||
fileIds.push(item.id)
|
||||
});
|
||||
subData1 = {
|
||||
detail_type: this.leavaTypeId1,
|
||||
content: this.meatelist.content,
|
||||
check_admin_name: this.check_admin_name,
|
||||
check_admin_ids: this.check_admin_ids,
|
||||
|
@ -622,54 +679,30 @@
|
|||
type: this.typeId,
|
||||
}
|
||||
|
||||
if (this.typeId == 8) {
|
||||
subData1.start_time = this.timeData[0].timeDay + ' ' + this.timeData[0].timeHour,
|
||||
subData1.end_time = this.timeData[1].timeDay + ' ' + this.timeData[1].timeHour,
|
||||
subData1.department_type = this.leavaTypeId
|
||||
subData1.detail_type = this.leavaTypeId1
|
||||
subData1.other_type = this.leavaTypeId2
|
||||
|
||||
}
|
||||
if (this.typeId == 21) {
|
||||
if (this.meatelist.hasOwnProperty('department_type')) {
|
||||
subData1.department_type = this.leavaTypeId
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('other_type')) {
|
||||
subData1.other_type = this.leavaTypeId2
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('position_type')) {
|
||||
subData1.position_type = this.leavaTypeId3
|
||||
// console.log(subData1.position_type , this.leavaTypeId3)
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('detail_type')) {
|
||||
subData1.detail_type = this.leavaTypeId1
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('num') && this.typeId == 20) {
|
||||
subData1.num = this.leavaTypeId4
|
||||
}
|
||||
if (this.meatelist.hasOwnProperty('num1') && this.typeId == 20) {
|
||||
subData1.num1 = this.leavaTypeId5
|
||||
}
|
||||
subData = {
|
||||
...this.meatelist,
|
||||
...subData1
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
let fileIds = [];
|
||||
this.fileArray.map((item, i) => {
|
||||
fileIds.push(item.id)
|
||||
});
|
||||
subData = {
|
||||
detail_type: this.leavaTypeId1,
|
||||
start_time: this.timeData[0].timeDay + ' ' + this.timeData[0].timeHour,
|
||||
end_time: this.timeData[1].timeDay + ' ' + this.timeData[1].timeHour,
|
||||
duration: this.manHour,
|
||||
content: this.meatelist.content,
|
||||
check_admin_name: this.check_admin_name,
|
||||
check_admin_ids: this.check_admin_ids,
|
||||
flow_id: this.flow_id,
|
||||
file_ids: fileIds.join(','),
|
||||
copy_names: this.copy_names,
|
||||
copy_uids: this.copy_uids,
|
||||
type: this.typeId,
|
||||
file: ''
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
console.log(subData)
|
||||
|
||||
try {
|
||||
|
@ -775,7 +808,7 @@
|
|||
/**
|
||||
* 计算两个时间戳之间相差的小时数
|
||||
* */
|
||||
calculateLeaveDaysAndHours(leaveStartTime, leaveEndTime, hoursPerDay = 8) {
|
||||
calculateLeaveDaysAndHours(leaveStartTime, leaveEndTime) {
|
||||
const startDate = new Date(leaveStartTime);
|
||||
const endDate = new Date(leaveEndTime);
|
||||
|
||||
|
@ -783,8 +816,12 @@
|
|||
const leaveDays = Math.floor((endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000)) + 1;
|
||||
|
||||
// 计算请假总小时数
|
||||
const leaveHours = leaveDays * hoursPerDay;
|
||||
// const leaveHours = leaveDays * hoursPerDay;
|
||||
const timeDifference = endDate.getTime() - startDate.getTime();
|
||||
|
||||
// 将时间差转换为小时数
|
||||
const leaveHours = timeDifference / (1000 * 60 * 60); // 将毫秒数转换为小时数
|
||||
// console.log(leaveHours)
|
||||
// 返回结果
|
||||
return {
|
||||
leaveDays,
|
||||
|
@ -822,7 +859,10 @@
|
|||
margin-bottom: 35.09rpx;
|
||||
padding-bottom: 28.07rpx;
|
||||
}
|
||||
|
||||
/deep/.u-action-sheet__item-wrap {
|
||||
overflow: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.bot_btn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
<template>
|
||||
<view class="leave_request">
|
||||
<view class="leave_box" v-for='(item,i) in dataobj' :key="i">
|
||||
{{ item.title }} - {{ item.type }}
|
||||
<view class="leave_box" v-for='(item,i) in dataobj' >
|
||||
{{item}}
|
||||
<view class="leava_type flex_a_c">
|
||||
<view class="title">{{dataobj[i].title}}:</view>
|
||||
<view class="title">请假类型:</view>
|
||||
<input type="text" v-model="leavaTypeVal" placeholder="请选择" disabled @click="leavaTypeShow = true">
|
||||
</view>
|
||||
{{i}}
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ dataobj[i]}}</view>
|
||||
<input type="text" v-model="item.time" placeholder="请选择时间" disabled @click="selectTime(item)">
|
||||
</view>
|
||||
|
||||
|
||||
<!-- <block v-for="(item,i) in timeData" :key="i">
|
||||
<block v-for="(item,i) in timeData" :key="i">
|
||||
<view class="cont_cell">
|
||||
<view class="title">{{ item.title }}</view>
|
||||
<input type="text" v-model="item.time" placeholder="请选择时间" disabled @click="selectTime(item)">
|
||||
</view>
|
||||
</block> -->
|
||||
</block>
|
||||
<view class="cont_cell">
|
||||
<view class="title">请假工时:</view>
|
||||
<input type="text" v-model="manHour" disabled placeholder="请假工时">
|
||||
|
@ -110,7 +103,9 @@
|
|||
|
||||
<script>
|
||||
|
||||
|
||||
import {
|
||||
oaLeaveData
|
||||
} from '@/static/server/server.js'
|
||||
import {
|
||||
oaUploads
|
||||
} from '../../api/upload'
|
||||
|
@ -462,7 +457,7 @@
|
|||
content: '确定删除图片?',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
that.fileArray.splice(i, 1)
|
||||
that.fileArray.splice((i, 1))
|
||||
} else if (res.cancel) {
|
||||
console.log('用户点击取消');
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
id: id
|
||||
|
||||
})
|
||||
console.log(res.data)
|
||||
|
||||
this.list = res.data
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j' @click="msg(items.id)"
|
||||
style="margin-bottom: 20rpx;">
|
||||
<liu-swipe-action :index="j">
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem(items)" :btnList='btnList'>
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
{{items.msg_type}}
|
||||
|
@ -49,38 +49,7 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle" :style="{'position':'absolute','top':0+'px','zIndex':999}" v-if="!screenShow">
|
||||
<view class="content-middle-one">
|
||||
<view class="middle-one">
|
||||
<view class="content-middle-search">
|
||||
<text class='iconfont icon-sousuo2'></text>
|
||||
<input type='text' :value='keyword' placeholder='搜索任务状态、优先级、部门等' placeholder-class='placeholder'
|
||||
@input="setValue"></input>
|
||||
</view>
|
||||
<view class="content-middle-sai" @click="screen" style="background-color: #3274F9;">
|
||||
<view class="content-middle-saia">
|
||||
<image src="../../static/images/saixuan.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="content-middle-saib" style="color: #fff;">
|
||||
筛选
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle-search-detail">
|
||||
<view class="search-detail" v-for="(item,k) in klist" :key='k'>
|
||||
<view class="search-detail-one">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-detail-two">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list.length==0" text="没有信息"
|
||||
icon="/static/empty/data.png"></u-empty>
|
||||
|
@ -93,7 +62,8 @@
|
|||
<script>
|
||||
import {
|
||||
appmessageinbox,
|
||||
appmessageread
|
||||
appmessageread,
|
||||
deletemessage
|
||||
} from '@/api/oa.js'
|
||||
import {
|
||||
HTTP_REQUEST_URL
|
||||
|
@ -107,14 +77,6 @@
|
|||
return {
|
||||
show: false,
|
||||
btnList: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
height: '100rpx',
|
||||
|
@ -185,14 +147,29 @@
|
|||
|
||||
},
|
||||
|
||||
clickItem(data) {
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(data.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
//删除
|
||||
},
|
||||
async deleteDepartment(id) {
|
||||
const res = await deletemessage({
|
||||
ids: id
|
||||
})
|
||||
Toast(res.msg)
|
||||
this.initList()
|
||||
},
|
||||
//详情
|
||||
async msg(id) {
|
||||
|
||||
const res = await appmessageread({
|
||||
id: id
|
||||
})
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/message/detail??type=' + id
|
||||
})
|
||||
|
@ -221,7 +198,6 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
padding-bottom: 88rpx;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<view class="middle-three">
|
||||
|
||||
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j' @click="deleteDepartment(items.id)">
|
||||
<view class="middle-threeb" v-for="(items,j) in list" :key='j'>
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList'>
|
||||
<view class="middle-threeb-title">
|
||||
<view class="title">
|
||||
|
@ -510,6 +510,7 @@
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
.content-middle-two {
|
||||
width: 386rpx;
|
||||
height: 70rpx;
|
||||
|
@ -540,6 +541,4 @@
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -147,7 +147,7 @@
|
|||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list2 = [];
|
||||
this.list = [];
|
||||
await this.getDocumentList();
|
||||
},
|
||||
//获取项目
|
||||
|
@ -186,7 +186,7 @@
|
|||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(this.list[data.index].id)
|
||||
this.initList()
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
<view class="achor">工作类型:<text>{{item.cate_name}}</text></view>
|
||||
<view class="achor">关联项目:<text>{{item.project_name}}</text></view>
|
||||
<view class="achor">预估工时:<text>{{item.plan_hours}}</text></view>
|
||||
<view class="middle-edit" @click="editpart(item)">
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
|
|
@ -24,11 +24,13 @@
|
|||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.status==1?'#34A853':item.status==2?'#F9AA32':item.status==3?'#F02828':''}">
|
||||
|
||||
<text v-if='item.status==1'>已通过</text>
|
||||
<text v-if='item.status==2'>待审批</text>
|
||||
<text v-if='item.status==3'>审批拒绝</text>
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">报销部门:{{item.department}}</view>
|
||||
|
@ -44,6 +46,10 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list2.length==0" text="没有信息"
|
||||
icon="/static/empty/data.png"></u-empty>
|
||||
<u-loadmore v-else :status="loadConfig.status" :loading-text="loadConfig.loadingText"
|
||||
:loadmore-text="loadConfig.loadmoreText" :nomore-text="loadConfig.nomoreText" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
@ -80,23 +86,7 @@
|
|||
],
|
||||
list2: [],
|
||||
num: 0,
|
||||
btnList: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
height: '100rpx',
|
||||
width: '100rpx',
|
||||
bgColor: '#ed656d',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}],
|
||||
btnList: [],
|
||||
loadConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
|
@ -158,7 +148,7 @@
|
|||
async initList2() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list3 = [];
|
||||
this.list2 = [];
|
||||
await this.getlist2()
|
||||
},
|
||||
async getlist() {
|
||||
|
@ -251,8 +241,14 @@
|
|||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.loadConfig.status = "loading"
|
||||
|
||||
if (this.num == 0) {
|
||||
this.initList()
|
||||
} else if (this.num == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
|
|
@ -426,6 +426,11 @@
|
|||
|
||||
|
||||
const res = await appexpense(this.listobj)
|
||||
if(res.code==0){
|
||||
uni.navigateBack({
|
||||
delta:1
|
||||
})
|
||||
}
|
||||
Toast('提交成功')
|
||||
|
||||
|
||||
|
|
|
@ -56,9 +56,10 @@
|
|||
|
||||
|
||||
</view>
|
||||
<view class="leave_box" style="padding-top: 100rpx;" v-if="fileArray.length>0">
|
||||
<!-- <view class="leave_box" style="padding-top: 100rpx;" v-if="fileArray.length>0"> -->
|
||||
|
||||
<!-- 附件 -->
|
||||
<view class="" style="background-color: #fff;">
|
||||
<block v-for="(item, i) in fileArray" :key="i">
|
||||
<view class="file flex_a_c_j_sb">
|
||||
<view class="l_file">
|
||||
|
@ -69,9 +70,10 @@
|
|||
<!-- <u-icon @click="delImg(i)" name="close-circle" color="#333333" size="28"></u-icon> -->
|
||||
</view>
|
||||
</block>
|
||||
|
||||
</view>
|
||||
<view class="leave_box" style="padding-top: 100rpx;" v-if="listobj.check_status!= 4&& ktype!=0">
|
||||
|
||||
|
||||
<view class="leave_box" style="padding-top: 100rpx;" v-if="listobj.check_status!= 4&& listobj.check_status!= 2&&ktype!=0">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;">
|
||||
<view class="title" style="width: 200rpx;">撤回意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入撤回意见" />
|
||||
|
@ -92,7 +94,7 @@
|
|||
<view class="cont_cell">
|
||||
<view class="title">审核状态:</view>
|
||||
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':'撤销审核'}}
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':listobj.check_status=='4'?'撤销审核':'已开具'}}
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">审核人:</view>
|
||||
|
@ -105,7 +107,7 @@
|
|||
|
||||
</view>
|
||||
|
||||
<view class="" v-if="ktype!=0">
|
||||
<view class="" v-if=" listobj.check_status!= 2&&ktype!=0">
|
||||
<view class="bot_btn" v-if="listobj.check_status!= 4">
|
||||
<!-- <view class="reset" @click="reset">重置</view> -->
|
||||
<view class="submit_btn" @click="submiteBtn">撤回</view>
|
||||
|
@ -118,8 +120,8 @@
|
|||
|
||||
|
||||
</view>
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择"
|
||||
@close="leavaTypeShow = false" @select="leavaType">
|
||||
<u-action-sheet :show="leavaTypeShow" keyName="name" :actions="columns" title="请选择" @close="leavaTypeShow = false"
|
||||
@select="leavaType">
|
||||
</u-action-sheet>
|
||||
<u-action-sheet :show="leavaTypeShow1" keyName="name" :actions="actions4" title="请选择"
|
||||
@close="leavaTypeShow1 = false" @select="leavaType1">
|
||||
|
@ -254,12 +256,16 @@
|
|||
this.check_record = res.data.check_record
|
||||
|
||||
this.listobj.check_status = res.data.detail.check_status
|
||||
|
||||
if ( res.data && res.data.detail && res.data.detail.fileArray) {
|
||||
this.fileArray = res.data.detail.fileArray.map(function(obj) {
|
||||
return {
|
||||
name: obj.name,
|
||||
filesize: obj.filesize
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(this.fileArray,'11111111111', res.data.detail)
|
||||
|
||||
},
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
|
||||
</view>
|
||||
<view class="leave_box" style="padding-top: 100rpx;">
|
||||
<view class="leave_box" style="padding-top: 100rpx; background-color: #fff;">
|
||||
|
||||
<!-- 附件 -->
|
||||
<block v-for="(item, i) in fileArray" :key="i">
|
||||
|
@ -81,7 +81,7 @@
|
|||
<view class="cont_cell">
|
||||
<view class="title">审核状态:</view>
|
||||
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':'撤销审核'}}
|
||||
{{listobj.check_status=='0'?'待审核':listobj.check_status=='1'?'审核中':listobj.check_status=='2'?'审核通过':listobj.check_status=='3'?'审核不通过':listobj.check_status=='4'?'审核不通过':'已打款'}}
|
||||
</view>
|
||||
<view class="cont_cell">
|
||||
<view class="title">审核人:</view>
|
||||
|
@ -99,7 +99,7 @@
|
|||
了此申请。操作意见:{{item.content}}</text>
|
||||
</view>
|
||||
</block>
|
||||
<view class="" >
|
||||
<view class="" v-if='listobj.check_status!=2'>
|
||||
<view class="title" style="margin-bottom: 30rpx;">审核节点:</view>
|
||||
<radio-group class="select_group" @change="deliveryWayChangetwo1" >
|
||||
<label class="radio_select" style="margin-right:15rpx;display: flex; margin-bottom: 30rpx;">
|
||||
|
@ -119,14 +119,14 @@
|
|||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="listobj.check_status!= 4">
|
||||
<view class="cont_cell" style="padding-top: 20rpx;" v-if="listobj.check_status!= 4&&listobj.check_status!=2">
|
||||
<view class="title" style="width: 200rpx;">审核意见</view>
|
||||
<textarea v-model="mscontent" placeholder="请输入审核意见" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="bot_btn">
|
||||
<view class="bot_btn" v-if='listobj.check_status!=2'>
|
||||
<view class="reset" @click="appflowcheck()">拒绝</view>
|
||||
<view class="submit_btn" @click=" appflowcheck1()">通过</view>
|
||||
</view>
|
||||
|
|
|
@ -125,12 +125,12 @@
|
|||
</u-action-sheet>
|
||||
|
||||
<!-- 部门选择 -->
|
||||
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns"
|
||||
<u-picker :show="branchShow" :defaultIndex='defaultIndex' ref="branchRef" :columns="branchColumns" @cancel='branchShowclose'
|
||||
@confirm="branchConfirm" @change="columnCode" :closeOnClickOverlay="true" @close="branchShowclose"
|
||||
keyName="name">
|
||||
</u-picker>
|
||||
|
||||
<u-picker :show="branchShow1" :defaultIndex='defaultIndex1' ref="branchRef" :columns="branchColumns1"
|
||||
<u-picker :show="branchShow1" :defaultIndex='defaultIndex1' ref="branchRef" :columns="branchColumns1" @cancel='branchShowclose1'
|
||||
@confirm="branchConfirm1" @change="columnCode1" :closeOnClickOverlay="true" @close="branchShowclose1"
|
||||
keyName="name">
|
||||
</u-picker>
|
||||
|
@ -205,7 +205,7 @@
|
|||
}
|
||||
},
|
||||
onLoad(option) {
|
||||
this.detail(option.type)
|
||||
// this.detail(option.type)
|
||||
},
|
||||
onShow() {
|
||||
this.fileOption = {
|
||||
|
@ -226,24 +226,7 @@
|
|||
|
||||
|
||||
methods: {
|
||||
async detail(id) {
|
||||
let res = await appexpenseview({
|
||||
id: id
|
||||
})
|
||||
// console.log(res,'111')
|
||||
this.listobj.code = res.data.detail.code
|
||||
this.listobj.id=id
|
||||
this.list=res.data.detail.list
|
||||
this.listobj.expense_time= res.data.detail.expense_time
|
||||
this.listobj.income_month = res.data.detail.income_month
|
||||
this.check_admin_name= res.data.detail.check_user
|
||||
this.copy_names= res.data.detail.copy_user
|
||||
this.project= res.data.detail.ptname
|
||||
this.listobj.flow_id=res.data.flows.id
|
||||
this.listobj.ptid= res.data.detail.ptid
|
||||
|
||||
|
||||
},
|
||||
reset() {
|
||||
this.list = [{
|
||||
name: "",
|
||||
|
@ -419,6 +402,11 @@
|
|||
|
||||
|
||||
const res = await appexpense(this.listobj)
|
||||
if(res.code==0){
|
||||
uni.navigateBack({
|
||||
delta:1
|
||||
})
|
||||
}
|
||||
Toast('提交成功')
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</view>
|
||||
<view class="content-middle-one">
|
||||
<view class="middle-one" v-for="(item,j) in list" :key='j'>
|
||||
|
||||
<liu-swipe-action :index="j" @clickItem="clickItem" :btnList='btnList'>
|
||||
<view class="middle-onea">
|
||||
<view class="middle-onea-title">
|
||||
{{item.name}}
|
||||
|
@ -31,16 +31,16 @@
|
|||
<view class="achor">职位:{{item.position}}</view>
|
||||
<view class="achor">部门负责人:{{item.lead_admin}}</view>
|
||||
<view class="achor">交接人:{{item.connect_names}}</view>
|
||||
<view class="textare-three">
|
||||
<view class="textare-three" v-if="item.remark.length>0">
|
||||
<textarea :value="item.remark" placeholder="" />
|
||||
</view>
|
||||
|
||||
<view class="middle-edit" @click="editpart(item)">
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
@ -50,7 +50,7 @@
|
|||
</view>
|
||||
|
||||
|
||||
|
||||
</liu-swipe-action>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
@ -85,6 +85,14 @@
|
|||
return {
|
||||
show: false,
|
||||
btnList: [{
|
||||
id: '1',
|
||||
name: '编辑',
|
||||
width: '100rpx',
|
||||
height: '100rpx',
|
||||
bgColor: '#5f92f7',
|
||||
color: '#FFFFFF',
|
||||
fontSize: '28rpx'
|
||||
}, {
|
||||
id: '2',
|
||||
name: '删除',
|
||||
width: '100rpx',
|
||||
|
@ -108,7 +116,7 @@ loadConfig: {
|
|||
};
|
||||
},
|
||||
onShow() {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
},
|
||||
onReachBottom() {
|
||||
this.getDocumentList()
|
||||
|
@ -117,16 +125,25 @@ loadConfig: {
|
|||
uni.stopPullDownRefresh()
|
||||
},
|
||||
methods: {
|
||||
|
||||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list = [];
|
||||
await this.getDocumentList()
|
||||
},
|
||||
|
||||
//获取离职档案
|
||||
|
||||
async getDocumentList() {
|
||||
|
||||
try {
|
||||
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
let res = await leaveuserpersonal({
|
||||
page: this.loadConfig.page,
|
||||
limit: this.loadConfig.limit,
|
||||
keyword: this.keyword
|
||||
|
||||
})
|
||||
|
||||
|
@ -137,9 +154,7 @@ loadConfig: {
|
|||
this.loadConfig.page++;
|
||||
}
|
||||
this.list = [...this.list, ...res.data?.data]
|
||||
} catch (e) {
|
||||
this.loadConfig.status = "nomore"
|
||||
}
|
||||
|
||||
},
|
||||
//添加离职档案
|
||||
adddepart() {
|
||||
|
@ -150,15 +165,20 @@ loadConfig: {
|
|||
//删除弹窗
|
||||
clickItem(data) {
|
||||
// console.log(e)
|
||||
if (data.id == 2) {
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(data.id)
|
||||
this.deleteDepartment(this.list[data.index].id)
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
this.editpart(this.list[data.index])
|
||||
}
|
||||
},
|
||||
|
||||
//删除
|
||||
|
@ -169,7 +189,7 @@ loadConfig: {
|
|||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
|
@ -185,13 +205,13 @@ loadConfig: {
|
|||
},
|
||||
//查询
|
||||
search() {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
},
|
||||
//输入监听
|
||||
setValue(e) {
|
||||
this.keyword = e.detail.value
|
||||
if (this.keyword.length == 0) {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
</view>
|
||||
<view class="content-middle-two">
|
||||
<view class="middle-two" v-for="(item,i) in list" :key='i'>
|
||||
<view class="middle-two" v-for="(item,i) in list" :key='i' @click="arryitem(item)">
|
||||
<view class="middle-twoa">
|
||||
<image :src="item.img" mode=""></image>
|
||||
</view>
|
||||
|
@ -30,7 +30,7 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle-three">
|
||||
<view class="content-middle-three" v-if="list2.length>0">
|
||||
<view class="middle-three" v-for="(item,k) in list2" :key='k'>
|
||||
|
||||
<view class="middle-threea">企业员工</view>
|
||||
|
@ -38,7 +38,8 @@
|
|||
<view class="middle-threeb">
|
||||
<view class="middle-threeb-a">
|
||||
<view class="threeb-a-a">
|
||||
<image :src="item.img" mode=""></image>
|
||||
<image src="@/static/images/gw.png" mode=""></image>
|
||||
|
||||
</view>
|
||||
<view class="threeb-a-b">
|
||||
<view class="name">{{item.department}} <text>({{item.name}})</text></view>
|
||||
|
@ -60,8 +61,8 @@
|
|||
<view class="middle-one">
|
||||
<view class="content-middle-search">
|
||||
<text class='iconfont icon-sousuo2'></text>
|
||||
<input type='text' :value='searchValue' placeholder='点击搜索商品、店铺名称'
|
||||
placeholder-class='placeholder' @input="setValue"></input>
|
||||
<input type='text' :value='keyword' placeholder='点击搜索商品、店铺名称' placeholder-class='placeholder'
|
||||
@input="setValue"></input>
|
||||
</view>
|
||||
<view class="content-middle-sai" @click="screen" style="background-color: #3274F9;">
|
||||
<view class="content-middle-saia">
|
||||
|
@ -73,26 +74,17 @@
|
|||
</view>
|
||||
</view>
|
||||
<view class="content-middle-search-detail">
|
||||
<view class="search-detail">
|
||||
<view class="search-detail" v-for="(item,i) in list3" :key='i' @click="saixun(item)">
|
||||
<view class="search-detail-one">
|
||||
<view class="name">
|
||||
员工状态
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-detail-two">
|
||||
正常登陆
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-detail">
|
||||
<view class="search-detail-one">
|
||||
<view class="name">
|
||||
员工状态
|
||||
</view>
|
||||
</view>
|
||||
<view class="search-detail-two">
|
||||
正常登陆
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -103,7 +95,7 @@
|
|||
</view>
|
||||
<view class="content-bootom-two">添加企业员工</view>
|
||||
</view>
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list.length==0" text="没有信息"
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list2.length==0" text="没有信息"
|
||||
icon="/static/empty/data.png"></u-empty>
|
||||
<u-loadmore v-else :status="loadConfig.status" :loading-text="loadConfig.loadingText"
|
||||
:loadmore-text="loadConfig.loadmoreText" :nomore-text="loadConfig.nomoreText" />
|
||||
|
@ -130,23 +122,44 @@
|
|||
name: '人力资源',
|
||||
keyword: '',
|
||||
list: [{
|
||||
name: '请假申请',
|
||||
img: require('@/static/images/s2.png')
|
||||
name: '部门架构',
|
||||
id: 1,
|
||||
img: require('@/static/images/r1.png')
|
||||
|
||||
}, {
|
||||
name: '出差申请',
|
||||
img: require('@/static/images/s4.png')
|
||||
name: '岗位职称',
|
||||
id: 2,
|
||||
img: require('@/static/images/r2.png')
|
||||
|
||||
}, {
|
||||
name: '请假申请',
|
||||
img: require('@/static/images/s3.png')
|
||||
name: '人事调动',
|
||||
id: 3,
|
||||
img: require('@/static/images/r3.png')
|
||||
|
||||
}, {
|
||||
name: '采购申请',
|
||||
img: require('@/static/images/s5.png')
|
||||
name: '离职档案',
|
||||
id: 4,
|
||||
img: require('@/static/images/r4.png')
|
||||
|
||||
}],
|
||||
|
||||
list2: [],
|
||||
list3: [{
|
||||
title: '禁止登录',
|
||||
id: 0
|
||||
|
||||
},
|
||||
{
|
||||
title: '正常',
|
||||
id: 1
|
||||
|
||||
}, {
|
||||
title: '离职',
|
||||
id: 2
|
||||
|
||||
}
|
||||
|
||||
],
|
||||
btnList: [{
|
||||
id: '2',
|
||||
name: '删除',
|
||||
|
@ -163,6 +176,7 @@
|
|||
nomoreText: '我也是有底线的~~',
|
||||
status: 'loadmore'
|
||||
},
|
||||
status: '',
|
||||
merchantData: {
|
||||
|
||||
},
|
||||
|
@ -183,6 +197,33 @@
|
|||
uni.stopPullDownRefresh()
|
||||
},
|
||||
methods: {
|
||||
arryitem(item) {
|
||||
console.log(item.id)
|
||||
switch (item.id) {
|
||||
|
||||
case 1:
|
||||
uni.navigateTo({
|
||||
url: '/pages/structure/index'
|
||||
})
|
||||
break;
|
||||
case 2:
|
||||
uni.navigateTo({
|
||||
url: '/pages/jobtitle/index'
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
uni.navigateTo({
|
||||
url: '/pages/personneltransfer/index'
|
||||
})
|
||||
|
||||
break;
|
||||
case 4:
|
||||
uni.navigateTo({
|
||||
url: '/pages/resignationprofile/index'
|
||||
})
|
||||
break;
|
||||
}
|
||||
},
|
||||
screen() {
|
||||
this.screenShow = !this.screenShow
|
||||
},
|
||||
|
@ -201,7 +242,8 @@
|
|||
let res = await comanyerlist({
|
||||
page: this.loadConfig.page,
|
||||
limit: this.loadConfig.limit,
|
||||
keyword: this.keyword
|
||||
status: this.status,
|
||||
keyword: this.keyword,
|
||||
})
|
||||
console.log(res.data.data)
|
||||
this.loadConfig.status = "loadmore"
|
||||
|
@ -229,6 +271,7 @@
|
|||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(data.id)
|
||||
this.initList()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -243,7 +286,7 @@
|
|||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
|
@ -257,15 +300,20 @@
|
|||
},
|
||||
//查询
|
||||
search() {
|
||||
this.getDocumentList()
|
||||
this.initList()
|
||||
},
|
||||
//输入监听
|
||||
setValue(e) {
|
||||
this.keyword = e.detail.value
|
||||
if (this.keyword.length == 0) {
|
||||
this.getDocumentList()
|
||||
}
|
||||
}
|
||||
this.initList()
|
||||
|
||||
},
|
||||
//筛选
|
||||
saixun(item) {
|
||||
this.status = item.id
|
||||
this.initList()
|
||||
this.screenShow = true
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -496,7 +544,7 @@
|
|||
margin-top: 5rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
margin-right: 40rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
|
|
|
@ -12,10 +12,11 @@
|
|||
<view class="middle-oneb">
|
||||
<view class="middle-oneb-a">
|
||||
<view class="threeb-a-a">
|
||||
<image :src="items.img" mode=""></image>
|
||||
<image src="@/static/images/gw.png" mode=""></image>
|
||||
</view>
|
||||
<view class="threeb-a-b">
|
||||
<view class="name"> <text>{{items.title}}</text></view>
|
||||
<view class="name" style="margin-bottom: 20rpx;"> <text>{{items.title}}</text>
|
||||
</view>
|
||||
<view class="achor">{{items.remark}}{{item.phone}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -106,7 +107,7 @@
|
|||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list1 = [];
|
||||
this.list = [];
|
||||
await this.getDocumentList();
|
||||
},
|
||||
//获取部门
|
||||
|
@ -204,6 +205,7 @@
|
|||
padding: 28rpx 28rpx;
|
||||
|
||||
.middle-one {
|
||||
|
||||
.middle-onea {
|
||||
font-size: 35rpx;
|
||||
font-family: PingFang SC-Bold, PingFang SC;
|
||||
|
@ -215,7 +217,7 @@
|
|||
.middle-oneb {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
margin-bottom: 25rpx;
|
||||
|
||||
.middle-oneb-a {
|
||||
display: flex;
|
||||
|
@ -261,7 +263,7 @@
|
|||
.middle-oneb-b {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-top: 45rpx;
|
||||
|
||||
|
||||
|
||||
image {
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
</view>
|
||||
<view class="work">
|
||||
<view class="wr_item">
|
||||
<view class="wr_t_left">(技术部):</view>
|
||||
<view class="wr_t_right">技术专业</view>
|
||||
<view class="wr_t_left">{{ oaUserInfo.department_name}}</view>
|
||||
<!-- <view class="wr_t_right">技术专业</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -95,7 +95,7 @@
|
|||
userInfo
|
||||
} from '@/api/oaUser.js'
|
||||
import {
|
||||
appmessageinbox
|
||||
msgcount
|
||||
} from '@/api/oa.js'
|
||||
|
||||
import {
|
||||
|
@ -111,11 +111,14 @@
|
|||
type: "warning",
|
||||
value: 100,
|
||||
uniMP: false,
|
||||
myOaData: [{
|
||||
name: '工资详情',
|
||||
icon: require('@/static/images/w1.png'),
|
||||
paths: '/pages/users/salarydetails/index'
|
||||
}, {
|
||||
myOaData: [
|
||||
// {
|
||||
// name: '工资详情',
|
||||
// icon: require('@/static/images/w1.png'),
|
||||
// paths: '/pages/users/salarydetails/index'
|
||||
// },
|
||||
|
||||
{
|
||||
name: '公示文档',
|
||||
icon: require('@/static/images/w2.png'),
|
||||
|
||||
|
@ -189,12 +192,8 @@
|
|||
},
|
||||
methods: {
|
||||
async listmsg() {
|
||||
let res = await appmessageinbox({
|
||||
page: 1,
|
||||
limit: 10000,
|
||||
|
||||
})
|
||||
this.value=res.data.data.length
|
||||
let res = await msgcount()
|
||||
this.value=res.data.msg_num
|
||||
|
||||
|
||||
},
|
||||
|
|
|
@ -51,8 +51,12 @@
|
|||
|
||||
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 20rpx 20rpx;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,474 @@
|
|||
<template>
|
||||
<view class="content">
|
||||
<view class="content-banner">
|
||||
<view class="" v-for="(item,i ) in list" :key="i" @click="apparent(i)">
|
||||
<view class="banner-name" :style="{'color':i==num?'#3274F9':''}">{{item.name}}</view>
|
||||
<view class="banner-xian" v-if='i==num'></view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="content-middle">
|
||||
|
||||
<view class="content-middle-one" v-if="num==0">
|
||||
<view class="middle-one" v-for="(item,k) in list2" @click="tian(item,num)">
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList'>
|
||||
|
||||
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开始时间{{item.start_time}}</view>
|
||||
<view class="middle-one-time">结束时间{{item.end_time}}</view>
|
||||
</liu-swipe-action>
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle-one" v-if="num==1">
|
||||
<view class="middle-one" v-for="(item,k) in list2" @click="tian(item,num)">
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList'>
|
||||
|
||||
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.check_user}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.code}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">报销部门:{{item.department}}</view>
|
||||
<view class="middle-one-time">入账月份:{{item.income_month}}</view>
|
||||
<view class="middle-one-time">报销人审核人:{{item.admin_name}}</view>
|
||||
</liu-swipe-action>
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-middle-one" v-if="num==2">
|
||||
<view class="middle-one" v-for="(item,k) in list2" @click="tian(item,num)">
|
||||
<liu-swipe-action :index="k" @clickItem="clickItem" :btnList='btnList'>
|
||||
|
||||
<view class="middle-one-title">
|
||||
<view class="one-titlea">
|
||||
<view class="name">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="parment">
|
||||
{{item.name1}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="one-titleb"
|
||||
:style="{'color':item.check_status==0?'#000':item.check_status==1?'#dddddd':item.check_status==2?'#34A853':item.check_status==3?'#F9AA32':'#F02828'}">
|
||||
<text v-if='item.check_status==0'>待审核</text>
|
||||
<text v-if='item.check_status==1'>审核中</text>
|
||||
<text v-if='item.check_status==2'>审核通过</text>
|
||||
<text v-if='item.check_status==3'>审核不通过</text>
|
||||
<text v-if='item.check_status==4'>撤销审核</text>
|
||||
<text v-if='item.check_status==5'>已开具</text>
|
||||
<text v-if='item.check_status==10'>已作废</text>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="middle-one-time">类型:{{item.flow_type}}</view>
|
||||
<view class="middle-one-time">开票金额:{{item.amount}}</view>
|
||||
<view class="middle-one-time">审核人{{item.check_user}}</view>
|
||||
</liu-swipe-action>
|
||||
|
||||
<!-- <view class="middle-edit" @click="editpart(item)">
|
||||
编辑
|
||||
</view>
|
||||
<view class="middle-delete" @click="clickItem(item)">
|
||||
删除
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-empty v-if="loadConfig.status=='nomore'&& list2.length==0" text="没有信息"
|
||||
icon="/static/empty/data.png"></u-empty>
|
||||
<u-loadmore v-else :status="loadConfig.status" :loading-text="loadConfig.loadingText"
|
||||
:loadmore-text="loadConfig.loadmoreText" :nomore-text="loadConfig.nomoreText" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
Toast
|
||||
} from '@/libs/uniApi.js'
|
||||
|
||||
import {
|
||||
|
||||
approvelist,
|
||||
apexpenselist,
|
||||
invoicelist
|
||||
|
||||
} from '@/api/oa.js'
|
||||
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
title: 'Hello',
|
||||
statusBarHeight: 0,
|
||||
list: [{
|
||||
name: '待审审批',
|
||||
value: 8
|
||||
}, {
|
||||
name: '待审报销',
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
name: '待审发票',
|
||||
value: 8
|
||||
}
|
||||
],
|
||||
list2: [],
|
||||
num: 0,
|
||||
btnList: [],
|
||||
loadConfig: {
|
||||
page: 1,
|
||||
limit: 5,
|
||||
loadingText: '努力加载中',
|
||||
loadmoreText: '轻轻上拉',
|
||||
nomoreText: '我也是有底线的~~',
|
||||
status: 'loadmore'
|
||||
},
|
||||
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
},
|
||||
onShow() {
|
||||
if (this.num == 0) {
|
||||
this.initList()
|
||||
} else if (this.num == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
if (this.num == 0) {
|
||||
this.getlist()
|
||||
} else if (this.num == 1) {
|
||||
this.getlist1()
|
||||
} else {
|
||||
this.getlist2()
|
||||
}
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
uni.stopPullDownRefresh()
|
||||
},
|
||||
methods: {
|
||||
apparent(index) {
|
||||
this.num = index
|
||||
if (index == 0) {
|
||||
this.initList()
|
||||
} else if (index == 1) {
|
||||
this.initList1()
|
||||
} else {
|
||||
this.initList2()
|
||||
}
|
||||
},
|
||||
async initList() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list2 = [];
|
||||
await this.getlist()
|
||||
},
|
||||
async initList1() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list2 = [];
|
||||
await this.getlist1()
|
||||
},
|
||||
async initList2() {
|
||||
this.loadConfig.page = 1;
|
||||
this.loadConfig.status = "loadmore";
|
||||
this.list2 = [];
|
||||
await this.getlist2()
|
||||
},
|
||||
async getlist() {
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
let res = await approvelist({
|
||||
page: this.loadConfig.page,
|
||||
limit: this.loadConfig.limit,
|
||||
// keyword: this.keyword
|
||||
})
|
||||
|
||||
this.loadConfig.status = "loadmore"
|
||||
if (res.data.data.length < this.loadConfig.limit) {
|
||||
this.loadConfig.status = "nomore"
|
||||
} else {
|
||||
this.loadConfig.page++;
|
||||
}
|
||||
this.list2 = [...this.list2, ...res.data?.data]
|
||||
|
||||
console.log(this.list2)
|
||||
},
|
||||
|
||||
async getlist1() {
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
let res = await apexpenselist({
|
||||
page: this.loadConfig.page,
|
||||
limit: this.loadConfig.limit,
|
||||
// keyword: this.keyword
|
||||
})
|
||||
|
||||
this.loadConfig.status = "loadmore"
|
||||
if (res.data.data.length < this.loadConfig.limit) {
|
||||
this.loadConfig.status = "nomore"
|
||||
} else {
|
||||
this.loadConfig.page++;
|
||||
}
|
||||
this.list2 = [...this.list2, ...res.data?.data]
|
||||
|
||||
|
||||
},
|
||||
async getlist2() {
|
||||
if (this.loadConfig.status == "nomore") return;
|
||||
this.loadConfig.status = "loading"
|
||||
let res = await invoicelist({
|
||||
page: this.loadConfig.page,
|
||||
limit: this.loadConfig.limit,
|
||||
// keyword: this.keyword
|
||||
})
|
||||
|
||||
this.loadConfig.status = "loadmore"
|
||||
if (res.data.data.length < this.loadConfig.limit) {
|
||||
this.loadConfig.status = "nomore"
|
||||
} else {
|
||||
this.loadConfig.page++;
|
||||
}
|
||||
this.list2 = [...this.list2, ...res.data?.data]
|
||||
},
|
||||
//添加项目
|
||||
adddepart() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/addquest/index?type=' + 0
|
||||
})
|
||||
},
|
||||
//删除弹窗
|
||||
clickItem(data) {
|
||||
// console.log(e)
|
||||
|
||||
if (data.id == 2) {
|
||||
uni.showModal({
|
||||
content: '确定要删除吗',
|
||||
success: (e) => {
|
||||
if (e.confirm) {
|
||||
this.deleteDepartment(data.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
this.editpart(this.list2[data.index])
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
//删除
|
||||
async deleteDepartment(id) {
|
||||
|
||||
const res = await deleteexpenseflow({
|
||||
id: id
|
||||
})
|
||||
|
||||
if (res.code == 0) {
|
||||
this.loadConfig.status = "loading"
|
||||
this.initList()
|
||||
|
||||
}
|
||||
Toast(res.msg);
|
||||
|
||||
},
|
||||
//编辑项目
|
||||
editpart(item) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/reimbursementapplication/index??type=' + item.type
|
||||
})
|
||||
},
|
||||
tian(item,num) {
|
||||
if (num == 0) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/leave_request/index?type=' + item.id
|
||||
})
|
||||
} else if (num == 1) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/reimbursementapplication/handle?type=' + item.id
|
||||
})
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: '/pages/invoice/handle?type=' + item.id
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
.content-banner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 40rpx;
|
||||
|
||||
.banner-name {
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.banner-xian {
|
||||
width: 70rpx;
|
||||
height: 5rpx;
|
||||
margin: 10rpx auto;
|
||||
background-color: #3274F9;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.content-middle {
|
||||
.content-middle-one {
|
||||
.middle-one {
|
||||
width: 694rpx;
|
||||
|
||||
margin: 0 auto;
|
||||
margin-bottom: 21rpx;
|
||||
background: #FFFFFF;
|
||||
padding: 0 25rpx;
|
||||
padding-bottom: 25rpx;
|
||||
|
||||
.middle-edit {
|
||||
width: 645rpx;
|
||||
height: 63rpx;
|
||||
line-height: 63rpx;
|
||||
background: #e6e5d9;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #000;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
}
|
||||
|
||||
.middle-delete {
|
||||
width: 645rpx;
|
||||
height: 63rpx;
|
||||
line-height: 63rpx;
|
||||
background: #F02828;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
|
||||
}
|
||||
|
||||
.middle-one-title {
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
|
||||
line-height: 82rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.one-titlea {
|
||||
display: flex;
|
||||
|
||||
|
||||
.name {
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang SC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.parment {
|
||||
font-size: 25rpx;
|
||||
font-family: PingFang SC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #3274F9;
|
||||
margin-top: 5rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.one-titleb {
|
||||
font-size: 32rpx;
|
||||
font-family: PingFang SC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.middle-one-detail {
|
||||
height: 90rpx;
|
||||
font-size: 28rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.middle-one-time {
|
||||
font-size: 25rpx;
|
||||
font-family: PingFang SC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-top: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,27 @@
|
|||
## 1.0.11(2023-10-29)
|
||||
1. imgMode默认值改成aspectFit
|
||||
## 1.0.10(2023-08-13)
|
||||
1. 优化nvue,方便自定义图标
|
||||
## 1.0.9(2023-07-28)
|
||||
1. 修改几个对应错误图标的BUG
|
||||
## 1.0.8(2023-07-24)
|
||||
1. 优化 支持base64图片
|
||||
## 1.0.7(2023-07-17)
|
||||
1. 修复 uv-icon 恢复uv-empty相关的图标
|
||||
## 1.0.6(2023-07-13)
|
||||
1. 修复icon设置name属性对应图标错误的BUG
|
||||
## 1.0.5(2023-07-04)
|
||||
1. 更新图标,删除一些不常用的图标
|
||||
2. 删除base64,修改成ttf文件引入读取图标
|
||||
3. 自定义图标文档说明:https://www.uvui.cn/guide/customIcon.html
|
||||
## 1.0.4(2023-07-03)
|
||||
1. 修复主题颜色在APP不生效的BUG
|
||||
## 1.0.3(2023-05-24)
|
||||
1. 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
|
||||
## 1.0.2(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.1(2023-05-10)
|
||||
1. 修复小程序中异常显示
|
||||
## 1.0.0(2023-05-04)
|
||||
新发版
|
|
@ -0,0 +1,160 @@
|
|||
export default {
|
||||
'uvicon-level': 'e68f',
|
||||
'uvicon-checkbox-mark': 'e659',
|
||||
'uvicon-folder': 'e694',
|
||||
'uvicon-movie': 'e67c',
|
||||
'uvicon-star-fill': 'e61e',
|
||||
'uvicon-star': 'e618',
|
||||
'uvicon-phone-fill': 'e6ac',
|
||||
'uvicon-phone': 'e6ba',
|
||||
'uvicon-apple-fill': 'e635',
|
||||
'uvicon-backspace': 'e64d',
|
||||
'uvicon-attach': 'e640',
|
||||
'uvicon-empty-data': 'e671',
|
||||
'uvicon-empty-address': 'e68a',
|
||||
'uvicon-empty-favor': 'e662',
|
||||
'uvicon-empty-car': 'e657',
|
||||
'uvicon-empty-order': 'e66b',
|
||||
'uvicon-empty-list': 'e672',
|
||||
'uvicon-empty-search': 'e677',
|
||||
'uvicon-empty-permission': 'e67d',
|
||||
'uvicon-empty-news': 'e67e',
|
||||
'uvicon-empty-history': 'e685',
|
||||
'uvicon-empty-coupon': 'e69b',
|
||||
'uvicon-empty-page': 'e60e',
|
||||
'uvicon-empty-wifi-off': 'e6cc',
|
||||
'uvicon-reload': 'e627',
|
||||
'uvicon-order': 'e695',
|
||||
'uvicon-server-man': 'e601',
|
||||
'uvicon-search': 'e632',
|
||||
'uvicon-more-dot-fill': 'e66f',
|
||||
'uvicon-scan': 'e631',
|
||||
'uvicon-map': 'e665',
|
||||
'uvicon-map-fill': 'e6a8',
|
||||
'uvicon-tags': 'e621',
|
||||
'uvicon-tags-fill': 'e613',
|
||||
'uvicon-eye': 'e664',
|
||||
'uvicon-eye-fill': 'e697',
|
||||
'uvicon-eye-off': 'e69c',
|
||||
'uvicon-eye-off-outline': 'e688',
|
||||
'uvicon-mic': 'e66d',
|
||||
'uvicon-mic-off': 'e691',
|
||||
'uvicon-calendar': 'e65c',
|
||||
'uvicon-trash': 'e623',
|
||||
'uvicon-trash-fill': 'e6ce',
|
||||
'uvicon-play-left': 'e6bf',
|
||||
'uvicon-play-right': 'e6b3',
|
||||
'uvicon-minus': 'e614',
|
||||
'uvicon-plus': 'e625',
|
||||
'uvicon-info-circle': 'e69f',
|
||||
'uvicon-info-circle-fill': 'e6a7',
|
||||
'uvicon-question-circle': 'e622',
|
||||
'uvicon-question-circle-fill': 'e6bc',
|
||||
'uvicon-close': 'e65a',
|
||||
'uvicon-checkmark': 'e64a',
|
||||
'uvicon-checkmark-circle': 'e643',
|
||||
'uvicon-checkmark-circle-fill': 'e668',
|
||||
'uvicon-setting': 'e602',
|
||||
'uvicon-setting-fill': 'e6d0',
|
||||
'uvicon-heart': 'e6a2',
|
||||
'uvicon-heart-fill': 'e68b',
|
||||
'uvicon-camera': 'e642',
|
||||
'uvicon-camera-fill': 'e650',
|
||||
'uvicon-more-circle': 'e69e',
|
||||
'uvicon-more-circle-fill': 'e684',
|
||||
'uvicon-chat': 'e656',
|
||||
'uvicon-chat-fill': 'e63f',
|
||||
'uvicon-bag': 'e647',
|
||||
'uvicon-error-circle': 'e66e',
|
||||
'uvicon-error-circle-fill': 'e655',
|
||||
'uvicon-close-circle': 'e64e',
|
||||
'uvicon-close-circle-fill': 'e666',
|
||||
'uvicon-share': 'e629',
|
||||
'uvicon-share-fill': 'e6bb',
|
||||
'uvicon-share-square': 'e6c4',
|
||||
'uvicon-shopping-cart': 'e6cb',
|
||||
'uvicon-shopping-cart-fill': 'e630',
|
||||
'uvicon-bell': 'e651',
|
||||
'uvicon-bell-fill': 'e604',
|
||||
'uvicon-list': 'e690',
|
||||
'uvicon-list-dot': 'e6a9',
|
||||
'uvicon-zhifubao-circle-fill': 'e617',
|
||||
'uvicon-weixin-circle-fill': 'e6cd',
|
||||
'uvicon-weixin-fill': 'e620',
|
||||
'uvicon-qq-fill': 'e608',
|
||||
'uvicon-qq-circle-fill': 'e6b9',
|
||||
'uvicon-moments-circel-fill': 'e6c2',
|
||||
'uvicon-moments': 'e6a0',
|
||||
'uvicon-car': 'e64f',
|
||||
'uvicon-car-fill': 'e648',
|
||||
'uvicon-warning-fill': 'e6c7',
|
||||
'uvicon-warning': 'e6c1',
|
||||
'uvicon-clock-fill': 'e64b',
|
||||
'uvicon-clock': 'e66c',
|
||||
'uvicon-edit-pen': 'e65d',
|
||||
'uvicon-edit-pen-fill': 'e679',
|
||||
'uvicon-email': 'e673',
|
||||
'uvicon-email-fill': 'e683',
|
||||
'uvicon-minus-circle': 'e6a5',
|
||||
'uvicon-plus-circle': 'e603',
|
||||
'uvicon-plus-circle-fill': 'e611',
|
||||
'uvicon-file-text': 'e687',
|
||||
'uvicon-file-text-fill': 'e67f',
|
||||
'uvicon-pushpin': 'e6d1',
|
||||
'uvicon-pushpin-fill': 'e6b6',
|
||||
'uvicon-grid': 'e68c',
|
||||
'uvicon-grid-fill': 'e698',
|
||||
'uvicon-play-circle': 'e6af',
|
||||
'uvicon-play-circle-fill': 'e62a',
|
||||
'uvicon-pause-circle-fill': 'e60c',
|
||||
'uvicon-pause': 'e61c',
|
||||
'uvicon-pause-circle': 'e696',
|
||||
'uvicon-gift-fill': 'e6b0',
|
||||
'uvicon-gift': 'e680',
|
||||
'uvicon-kefu-ermai': 'e660',
|
||||
'uvicon-server-fill': 'e610',
|
||||
'uvicon-coupon-fill': 'e64c',
|
||||
'uvicon-coupon': 'e65f',
|
||||
'uvicon-integral': 'e693',
|
||||
'uvicon-integral-fill': 'e6b1',
|
||||
'uvicon-home-fill': 'e68e',
|
||||
'uvicon-home': 'e67b',
|
||||
'uvicon-account': 'e63a',
|
||||
'uvicon-account-fill': 'e653',
|
||||
'uvicon-thumb-down-fill': 'e628',
|
||||
'uvicon-thumb-down': 'e60a',
|
||||
'uvicon-thumb-up': 'e612',
|
||||
'uvicon-thumb-up-fill': 'e62c',
|
||||
'uvicon-lock-fill': 'e6a6',
|
||||
'uvicon-lock-open': 'e68d',
|
||||
'uvicon-lock-opened-fill': 'e6a1',
|
||||
'uvicon-lock': 'e69d',
|
||||
'uvicon-red-packet': 'e6c3',
|
||||
'uvicon-photo-fill': 'e6b4',
|
||||
'uvicon-photo': 'e60d',
|
||||
'uvicon-volume-off-fill': 'e6c8',
|
||||
'uvicon-volume-off': 'e6bd',
|
||||
'uvicon-volume-fill': 'e624',
|
||||
'uvicon-volume': 'e605',
|
||||
'uvicon-download': 'e670',
|
||||
'uvicon-arrow-up-fill': 'e636',
|
||||
'uvicon-arrow-down-fill': 'e638',
|
||||
'uvicon-play-left-fill': 'e6ae',
|
||||
'uvicon-play-right-fill': 'e6ad',
|
||||
'uvicon-arrow-downward': 'e634',
|
||||
'uvicon-arrow-leftward': 'e63b',
|
||||
'uvicon-arrow-rightward': 'e644',
|
||||
'uvicon-arrow-upward': 'e641',
|
||||
'uvicon-arrow-down': 'e63e',
|
||||
'uvicon-arrow-right': 'e63c',
|
||||
'uvicon-arrow-left': 'e646',
|
||||
'uvicon-arrow-up': 'e633',
|
||||
'uvicon-skip-back-left': 'e6c5',
|
||||
'uvicon-skip-forward-right': 'e61f',
|
||||
'uvicon-arrow-left-double': 'e637',
|
||||
'uvicon-man': 'e675',
|
||||
'uvicon-woman': 'e626',
|
||||
'uvicon-en': 'e6b8',
|
||||
'uvicon-twitte': 'e607',
|
||||
'uvicon-twitter-circle-fill': 'e6cf'
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
export default {
|
||||
props: {
|
||||
// 图标类名
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 图标颜色,可接受主题色
|
||||
color: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// 字体大小,单位px
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: '16px'
|
||||
},
|
||||
// 是否显示粗体
|
||||
bold: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
|
||||
index: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
// 触摸图标时的类名
|
||||
hoverClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 自定义扩展前缀,方便用户扩展自己的图标库
|
||||
customPrefix: {
|
||||
type: String,
|
||||
default: 'uvicon'
|
||||
},
|
||||
// 图标右边或者下面的文字
|
||||
label: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// label的位置,只能右边或者下边
|
||||
labelPos: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
// label的大小
|
||||
labelSize: {
|
||||
type: [String, Number],
|
||||
default: '15px'
|
||||
},
|
||||
// label的颜色
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// label与图标的距离
|
||||
space: {
|
||||
type: [String, Number],
|
||||
default: '3px'
|
||||
},
|
||||
// 图片的mode
|
||||
imgMode: {
|
||||
type: String,
|
||||
default: 'aspectFit'
|
||||
},
|
||||
// 用于显示图片小图标时,图片的宽度
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 用于显示图片小图标时,图片的高度
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 用于解决某些情况下,让图标垂直居中的用途
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 是否阻止事件传播
|
||||
stop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.icon
|
||||
}
|
||||
}
|
|
@ -0,0 +1,226 @@
|
|||
<template>
|
||||
<view
|
||||
class="uv-icon"
|
||||
@tap="clickHandler"
|
||||
:class="['uv-icon--' + labelPos]"
|
||||
>
|
||||
<image
|
||||
class="uv-icon__img"
|
||||
v-if="isImg"
|
||||
:src="name"
|
||||
:mode="imgMode"
|
||||
:style="[imgStyle, $uv.addStyle(customStyle)]"
|
||||
></image>
|
||||
<text
|
||||
v-else
|
||||
class="uv-icon__icon"
|
||||
:class="uClasses"
|
||||
:style="[iconStyle, $uv.addStyle(customStyle)]"
|
||||
:hover-class="hoverClass"
|
||||
>{{icon}}</text>
|
||||
<!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
|
||||
<text
|
||||
v-if="label !== ''"
|
||||
class="uv-icon__label"
|
||||
:style="{
|
||||
color: labelColor,
|
||||
fontSize: $uv.addUnit(labelSize),
|
||||
marginLeft: labelPos == 'right' ? $uv.addUnit(space) : 0,
|
||||
marginTop: labelPos == 'bottom' ? $uv.addUnit(space) : 0,
|
||||
marginRight: labelPos == 'left' ? $uv.addUnit(space) : 0,
|
||||
marginBottom: labelPos == 'top' ? $uv.addUnit(space) : 0
|
||||
}"
|
||||
>{{ label }}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
// #ifdef APP-NVUE
|
||||
// nvue通过weex的dom模块引入字体,相关文档地址如下:
|
||||
// https://weex.apache.org/zh/docs/modules/dom.html#addrule
|
||||
import iconUrl from './uvicons.ttf';
|
||||
const domModule = weex.requireModule('dom')
|
||||
domModule.addRule('fontFace', {
|
||||
'fontFamily': "uvicon-iconfont",
|
||||
'src': "url('" + iconUrl + "')"
|
||||
})
|
||||
// #endif
|
||||
// 引入图标名称,已经对应的unicode
|
||||
import icons from './icons';
|
||||
import props from './props.js';
|
||||
/**
|
||||
* icon 图标
|
||||
* @description 基于字体的图标集,包含了大多数常见场景的图标。
|
||||
* @tutorial https://www.uvui.cn/components/icon.html
|
||||
* @property {String} name 图标名称,见示例图标集
|
||||
* @property {String} color 图标颜色,可接受主题色 (默认 color['uv-content-color'] )
|
||||
* @property {String | Number} size 图标字体大小,单位px (默认 '16px' )
|
||||
* @property {Boolean} bold 是否显示粗体 (默认 false )
|
||||
* @property {String | Number} index 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
|
||||
* @property {String} hoverClass 图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
|
||||
* @property {String} customPrefix 自定义扩展前缀,方便用户扩展自己的图标库 (默认 'uicon' )
|
||||
* @property {String | Number} label 图标右侧的label文字
|
||||
* @property {String} labelPos label相对于图标的位置,只能right或bottom (默认 'right' )
|
||||
* @property {String | Number} labelSize label字体大小,单位px (默认 '15px' )
|
||||
* @property {String} labelColor 图标右侧的label文字颜色 ( 默认 color['uv-content-color'] )
|
||||
* @property {String | Number} space label与图标的距离,单位px (默认 '3px' )
|
||||
* @property {String} imgMode 图片的mode
|
||||
* @property {String | Number} width 显示图片小图标时的宽度
|
||||
* @property {String | Number} height 显示图片小图标时的高度
|
||||
* @property {String | Number} top 图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途 (默认 0 )
|
||||
* @property {Boolean} stop 是否阻止事件传播 (默认 false )
|
||||
* @property {Object} customStyle icon的样式,对象形式
|
||||
* @event {Function} click 点击图标时触发
|
||||
* @event {Function} touchstart 事件触摸时触发
|
||||
* @example <uv-icon name="photo" color="#2979ff" size="28"></uv-icon>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-icon',
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
colorType: [
|
||||
'primary',
|
||||
'success',
|
||||
'info',
|
||||
'error',
|
||||
'warning'
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
uClasses() {
|
||||
let classes = []
|
||||
classes.push(this.customPrefix)
|
||||
classes.push(this.customPrefix + '-' + this.name)
|
||||
// 主题色,通过类配置
|
||||
if (this.color && this.colorType.includes(this.color)) classes.push('uv-icon__icon--' + this.color)
|
||||
// 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
|
||||
// 故需将其拆成一个字符串的形式,通过空格隔开各个类名
|
||||
//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
|
||||
classes = classes.join(' ')
|
||||
//#endif
|
||||
return classes
|
||||
},
|
||||
iconStyle() {
|
||||
let style = {}
|
||||
style = {
|
||||
fontSize: this.$uv.addUnit(this.size),
|
||||
lineHeight: this.$uv.addUnit(this.size),
|
||||
fontWeight: this.bold ? 'bold' : 'normal',
|
||||
// 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
|
||||
top: this.$uv.addUnit(this.top)
|
||||
}
|
||||
// 非主题色值时,才当作颜色值
|
||||
if (this.color && !this.colorType.includes(this.color)) style.color = this.color
|
||||
return style
|
||||
},
|
||||
// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
|
||||
isImg() {
|
||||
const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
|
||||
return this.name.indexOf('/') !== -1 || isBase64;
|
||||
},
|
||||
imgStyle() {
|
||||
let style = {}
|
||||
// 如果设置width和height属性,则优先使用,否则使用size属性
|
||||
style.width = this.width ? this.$uv.addUnit(this.width) : this.$uv.addUnit(this.size)
|
||||
style.height = this.height ? this.$uv.addUnit(this.height) : this.$uv.addUnit(this.size)
|
||||
return style
|
||||
},
|
||||
// 通过图标名,查找对应的图标
|
||||
icon() {
|
||||
// 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
|
||||
const code = icons['uvicon-' + this.name];
|
||||
// #ifdef APP-NVUE
|
||||
if(!code) {
|
||||
return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? unescape(`%u${this.name}`) : '';
|
||||
}
|
||||
// #endif
|
||||
return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? this.name : '';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickHandler(e) {
|
||||
this.$emit('click', this.index)
|
||||
// 是否阻止事件冒泡
|
||||
this.stop && this.preventEvent(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
// 变量定义
|
||||
$uv-icon-primary: $uv-primary !default;
|
||||
$uv-icon-success: $uv-success !default;
|
||||
$uv-icon-info: $uv-info !default;
|
||||
$uv-icon-warning: $uv-warning !default;
|
||||
$uv-icon-error: $uv-error !default;
|
||||
$uv-icon-label-line-height: 1 !default;
|
||||
/* #ifndef APP-NVUE */
|
||||
// 非nvue下加载字体
|
||||
@font-face {
|
||||
font-family: 'uvicon-iconfont';
|
||||
src: url('./uvicons.ttf') format('truetype');
|
||||
}
|
||||
/* #endif */
|
||||
.uv-icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
&--left {
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
&--right {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
&--top {
|
||||
flex-direction: column-reverse;
|
||||
justify-content: center;
|
||||
}
|
||||
&--bottom {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
&__icon {
|
||||
font-family: uvicon-iconfont;
|
||||
position: relative;
|
||||
@include flex;
|
||||
align-items: center;
|
||||
&--primary {
|
||||
color: $uv-icon-primary;
|
||||
}
|
||||
&--success {
|
||||
color: $uv-icon-success;
|
||||
}
|
||||
&--error {
|
||||
color: $uv-icon-error;
|
||||
}
|
||||
&--warning {
|
||||
color: $uv-icon-warning;
|
||||
}
|
||||
&--info {
|
||||
color: $uv-icon-info;
|
||||
}
|
||||
}
|
||||
&__img {
|
||||
/* #ifndef APP-NVUE */
|
||||
height: auto;
|
||||
will-change: transform;
|
||||
/* #endif */
|
||||
}
|
||||
&__label {
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: $uv-icon-label-line-height;
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
</style>
|
Binary file not shown.
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"id": "uv-icon",
|
||||
"displayName": "uv-icon 图标 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.11",
|
||||
"description": "基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。可自定义颜色、大小。",
|
||||
"keywords": [
|
||||
"uv-ui,uvui,uv-icon,icon,图标,字体图标"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
## uv-icon 图标库
|
||||
|
||||
> **组件名:uv-icon**
|
||||
|
||||
基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/icon.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
|
@ -0,0 +1,11 @@
|
|||
## 1.0.4(2023-10-13)
|
||||
1. 优化
|
||||
## 1.0.3(2023-10-13)
|
||||
1. unmounted兼容vue3
|
||||
## 1.0.2(2023-05-27)
|
||||
1. 不支持抖音小程序说明
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-swipe-action 滑动单元格
|
|
@ -0,0 +1,256 @@
|
|||
/**
|
||||
* 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
|
||||
* wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
|
||||
*/
|
||||
|
||||
// 开始触摸
|
||||
function touchstart(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
|
||||
var state = instance.getState()
|
||||
if (state.disable) return
|
||||
var touches = event.touches
|
||||
// 如果进行的是多指触控,不允许进行操作
|
||||
if (touches && touches.length > 1) return
|
||||
// 标识当前为滑动中状态
|
||||
state.moving = true
|
||||
// 记录触摸开始点的坐标值
|
||||
state.startX = touches[0].pageX
|
||||
state.startY = touches[0].pageY
|
||||
}
|
||||
|
||||
// 触摸滑动
|
||||
function touchmove(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (state.disabled || !state.moving) return
|
||||
|
||||
var touches = event.touches
|
||||
var pageX = touches[0].pageX
|
||||
var pageY = touches[0].pageY
|
||||
var moveX = pageX - state.startX
|
||||
var moveY = pageY - state.startY
|
||||
var buttonsWidth = state.buttonsWidth
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (state.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
|
||||
moveSwipeAction(moveX, instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
function touchend(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (!state.moving || state.disabled) return
|
||||
var touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
var pageX = touches.pageX
|
||||
var pageY = touches.pageY
|
||||
var moveX = pageX - state.startX
|
||||
if (state.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (moveX < 0) return
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (moveX === 0) {
|
||||
return closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (moveX > 0) return
|
||||
// 理由同上
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过渡时间
|
||||
function getDuration(value) {
|
||||
if (value.toString().indexOf('s') >= 0) return value
|
||||
return value > 30 ? value + 'ms' : value + 's'
|
||||
}
|
||||
|
||||
// 滑动结束时判断滑动的方向
|
||||
function getMoveDirection(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
}
|
||||
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
function moveSwipeAction(moveX, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
var previewButtonsMoveX = 0
|
||||
|
||||
// 设置菜单内容部分的偏移
|
||||
instance.requestAnimationFrame(function() {
|
||||
instance.setStyle({
|
||||
// 设置translateX的值
|
||||
'transition': 'none',
|
||||
transform: 'translateX(' + moveX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + moveX + 'px)'
|
||||
})
|
||||
// 折叠按钮动画
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
var translateX = state.buttons[i].width / state.buttonsWidth * moveX
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
var realTranslateX = translateX + previewButtonsMoveX
|
||||
buttons[i].setStyle({
|
||||
// 在移动期间,不能使用过渡效果,否则会造成卡顿,本质原因是每次移动一点,就要花一定时间去过渡这个过程
|
||||
'transition': 'none',
|
||||
'transform': 'translateX(' + realTranslateX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + realTranslateX + 'px)'
|
||||
})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 一次性展开滑动菜单
|
||||
function openSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
const duration = getDuration(state.duration)
|
||||
// 展开过程中,是向左移动,所以X的偏移应该为负值
|
||||
var buttonsWidth = -state.buttonsWidth
|
||||
var previewButtonsMoveX = 0
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
'-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
})
|
||||
// 设置各个隐藏的按钮为展开的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
var translateX = state.buttons[i].width / state.buttonsWidth * buttonsWidth
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
var realTranslateX = translateX + previewButtonsMoveX
|
||||
buttons[i].setStyle({
|
||||
// 在移动期间,需要加上动画效果
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + realTranslateX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + realTranslateX + 'px)'
|
||||
})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
})
|
||||
setStatus('open', instance)
|
||||
}
|
||||
|
||||
// 标记菜单的当前状态,open-已经打开,close-已经关闭
|
||||
function setStatus(status, instance) {
|
||||
var state = instance.getState()
|
||||
state.status = status
|
||||
}
|
||||
|
||||
// 一次性收起滑动菜单
|
||||
function closeSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
const duration = getDuration(state.duration)
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
// 设置各个隐藏的按钮为收起的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
buttons[i].setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
}
|
||||
})
|
||||
setStatus('close', instance)
|
||||
}
|
||||
|
||||
// show的状态发生变化
|
||||
function showChange(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
// 打开或关闭单元格
|
||||
if (newValue) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单尺寸发生变化
|
||||
function sizeChange(newValue, oldValue, ownerInstance, instance) {
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
state.disabled = newValue.disabled
|
||||
state.duration = newValue.duration
|
||||
state.show = newValue.show
|
||||
state.threshold = newValue.threshold
|
||||
state.buttons = newValue.buttons
|
||||
|
||||
var len = state.buttons.length
|
||||
if (len) {
|
||||
var buttonsWidth = 0
|
||||
var buttons = newValue.buttons
|
||||
for (var i = 0; i < len; i++) {
|
||||
buttonsWidth += buttons[i].width
|
||||
}
|
||||
}
|
||||
state.buttonsWidth = buttonsWidth
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
sizeChange: sizeChange
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
* 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
|
||||
* wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
|
||||
*/
|
||||
|
||||
// 开始触摸
|
||||
function touchstart(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
var touches = event.touches
|
||||
// 如果进行的是多指触控,不允许进行操作
|
||||
if (touches && touches.length > 1) return
|
||||
// 标识当前为滑动中状态
|
||||
state.moving = true
|
||||
// 记录触摸开始点的坐标值
|
||||
state.startX = touches[0].pageX
|
||||
state.startY = touches[0].pageY
|
||||
|
||||
ownerInstance.callMethod('closeOther')
|
||||
}
|
||||
|
||||
// 触摸滑动
|
||||
function touchmove(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (state.disabled || !state.moving) return
|
||||
var touches = event.touches
|
||||
var pageX = touches[0].pageX
|
||||
var pageY = touches[0].pageY
|
||||
var moveX = pageX - state.startX
|
||||
var moveY = pageY - state.startY
|
||||
var buttonsWidth = state.buttonsWidth
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
|
||||
event.preventDefault && event.preventDefault()
|
||||
event.stopPropagation && event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (state.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动单元格内容部分,从而使隐藏的菜单显示出来
|
||||
moveSwipeAction(moveX, instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
function touchend(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (!state.moving || state.disabled) return
|
||||
var touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
var pageX = touches.pageX
|
||||
var pageY = touches.pageY
|
||||
var moveX = pageX - state.startX
|
||||
if (state.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (moveX < 0) return
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (moveX === 0) {
|
||||
return closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (moveX > 0) return
|
||||
// 理由同上
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过渡时间
|
||||
function getDuration(value) {
|
||||
if (value.toString().indexOf('s') >= 0) return value
|
||||
return value > 30 ? value + 'ms' : value + 's'
|
||||
}
|
||||
|
||||
// 滑动结束时判断滑动的方向
|
||||
function getMoveDirection(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
}
|
||||
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
function moveSwipeAction(moveX, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
|
||||
// 设置菜单内容部分的偏移
|
||||
instance.requestAnimationFrame(function() {
|
||||
instance.setStyle({
|
||||
// 设置translateX的值
|
||||
'transition': 'none',
|
||||
transform: 'translateX(' + moveX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + moveX + 'px)'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 一次性展开滑动菜单
|
||||
function openSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
// 处理duration单位问题
|
||||
var duration = getDuration(state.duration)
|
||||
// 展开过程中,是向左移动,所以X的偏移应该为负值
|
||||
var buttonsWidth = -state.buttonsWidth
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
'-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
})
|
||||
})
|
||||
setStatus('open', instance, ownerInstance)
|
||||
}
|
||||
|
||||
// 标记菜单的当前状态,open-已经打开,close-已经关闭
|
||||
function setStatus(status, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
state.status = status
|
||||
ownerInstance.callMethod('setState', status)
|
||||
}
|
||||
|
||||
// 一次性收起滑动菜单
|
||||
function closeSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
var duration = getDuration(state.duration)
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
// 设置各个隐藏的按钮为收起的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
buttons[i].setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
}
|
||||
})
|
||||
setStatus('close', instance, ownerInstance)
|
||||
}
|
||||
|
||||
// status的状态发生变化
|
||||
function statusChange(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
// 打开或关闭单元格
|
||||
if (newValue === 'close' && state.status === 'open') {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else if(newValue === 'open' && state.status === 'close') {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单尺寸发生变化
|
||||
function sizeChange(newValue, oldValue, ownerInstance, instance) {
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
state.disabled = newValue.disabled
|
||||
state.duration = newValue.duration
|
||||
state.show = newValue.show
|
||||
state.threshold = newValue.threshold
|
||||
state.buttons = newValue.buttons
|
||||
|
||||
if (state.buttons) {
|
||||
var len = state.buttons.length
|
||||
var buttonsWidth = 0
|
||||
var buttons = newValue.buttons
|
||||
for (var i = 0; i < len; i++) {
|
||||
buttonsWidth += buttons[i].width
|
||||
}
|
||||
}
|
||||
state.buttonsWidth = buttonsWidth
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
sizeChange: sizeChange,
|
||||
statusChange: statusChange
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
// nvue操作dom的库,用于获取dom的尺寸信息
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// nvue中用于操作元素动画的库,类似于uni.animation,只不过uni.animation不能用于nvue
|
||||
const animation = uni.requireNativePlugin('animation')
|
||||
import { sleep } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 是否滑动中
|
||||
moving: false,
|
||||
// 状态,open-打开状态,close-关闭状态
|
||||
status: 'close',
|
||||
// 开始触摸点的X和Y轴坐标
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
// 所有隐藏按钮的尺寸信息数组
|
||||
buttons: [],
|
||||
// 所有按钮的总宽度
|
||||
buttonsWidth: 0,
|
||||
// 记录上一次移动的位置值
|
||||
moveX: 0,
|
||||
// 记录上一次滑动的位置,用于前后两次做对比,如果移动的距离小于某一阈值,则认为前后之间没有移动,为了解决可能存在的通信阻塞问题
|
||||
lastX: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 获取过渡时间
|
||||
getDuratin() {
|
||||
let duration = String(this.duration)
|
||||
// 如果ms为单位,返回ms的数值部分
|
||||
if (duration.indexOf('ms') >= 0) return parseInt(duration)
|
||||
// 如果s为单位,为了得到ms的数值,需要乘以1000
|
||||
if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
|
||||
// 如果值传了数值,且小于30,认为是s单位
|
||||
duration = Number(duration)
|
||||
return duration < 30 ? duration * 1000 : duration
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
immediate: true,
|
||||
handler(n) {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
sleep(20).then(() => {
|
||||
this.queryRect()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.closeSwipeAction()
|
||||
},
|
||||
// 触摸单元格
|
||||
touchstart(event) {
|
||||
if (this.disabled) return
|
||||
this.closeOther()
|
||||
const { touches } = event
|
||||
// 记录触摸开始点的坐标值
|
||||
this.startX = touches[0].pageX
|
||||
this.startY = touches[0].pageY
|
||||
},
|
||||
// // 触摸滑动
|
||||
touchmove(event) {
|
||||
if (this.disabled) return
|
||||
const { touches } = event
|
||||
const { pageX } = touches[0]
|
||||
const { pageY } = touches[0]
|
||||
let moveX = pageX - this.startX
|
||||
const moveY = pageY - this.startY
|
||||
const { buttonsWidth } = this
|
||||
const len = this.buttons.length
|
||||
|
||||
// 判断前后两次的移动距离,如果小于一定值,则不进行移动处理
|
||||
if (Math.abs(pageX - this.lastX) < 0.3) return
|
||||
this.lastX = pageX
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > this.threshold) {
|
||||
event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (this.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
this.moveSwipeAction(-buttonsWidth + moveX)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
|
||||
this.moveSwipeAction(moveX)
|
||||
}
|
||||
},
|
||||
// 单元格结束触摸
|
||||
touchend(event) {
|
||||
if (this.disabled) return
|
||||
const touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
const { pageX } = touches
|
||||
const { pageY } = touches
|
||||
const { buttonsWidth } = this
|
||||
this.moveX = pageX - this.startX
|
||||
if (this.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (this.moveX < 0) this.moveX = 0
|
||||
if (this.moveX > buttonsWidth) this.moveX = buttonsWidth
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (this.moveX === 0) {
|
||||
return this.closeSwipeAction()
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(this.moveX) < this.threshold) {
|
||||
this.openSwipeAction()
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
this.closeSwipeAction()
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (this.moveX >= 0) this.moveX = 0
|
||||
if (this.moveX <= -buttonsWidth) this.moveX = -buttonsWidth
|
||||
// 理由同上
|
||||
if (Math.abs(this.moveX) < this.threshold) {
|
||||
this.closeSwipeAction()
|
||||
} else {
|
||||
this.openSwipeAction()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
moveSwipeAction(moveX) {
|
||||
if (this.moving) return
|
||||
this.moving = true
|
||||
|
||||
let previewButtonsMoveX = 0
|
||||
const len = this.buttons.length
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: `translateX(${moveX}px)`
|
||||
},
|
||||
timingFunction: 'linear'
|
||||
}, () => {
|
||||
this.moving = false
|
||||
})
|
||||
// 按钮的组的长度
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
const translateX = this.buttons[i].width / this.buttonsWidth * moveX
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
const realTranslateX = translateX + previewButtonsMoveX
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: `translateX(${realTranslateX}px)`
|
||||
},
|
||||
duration: 0,
|
||||
delay: 0,
|
||||
timingFunction: 'linear'
|
||||
}, () => {})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
},
|
||||
// 关闭菜单
|
||||
closeSwipeAction() {
|
||||
if (this.status === 'close') return
|
||||
this.moving = true
|
||||
const { buttonsWidth } = this
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: 'translateX(0px)'
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.status = 'close'
|
||||
this.moving = false
|
||||
this.closeHandler()
|
||||
})
|
||||
// 按钮的组的长度
|
||||
const len = this.buttons.length
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 如果不满足边界条件,返回
|
||||
if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
|
||||
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: 'translateX(0px)'
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {})
|
||||
}
|
||||
},
|
||||
// 打开菜单
|
||||
openSwipeAction() {
|
||||
if (this.status === 'open') return
|
||||
this.moving = true
|
||||
const buttonsWidth = -this.buttonsWidth
|
||||
let previewButtonsMoveX = 0
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: `translateX(${buttonsWidth}px)`
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.status = 'open'
|
||||
this.moving = false
|
||||
this.openHandler()
|
||||
})
|
||||
// 按钮的组的长度
|
||||
const len = this.buttons.length
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 如果不满足边界条件,返回
|
||||
if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
const translateX = this.buttons[i].width / this.buttonsWidth * buttonsWidth
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
const realTranslateX = translateX + previewButtonsMoveX
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: `translateX(${realTranslateX}px)`
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {})
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
},
|
||||
// 查询按钮节点信息
|
||||
queryRect() {
|
||||
// 历遍所有按钮数组,通过getRectByDom返回一个promise
|
||||
const promiseAll = this.rightOptions.map((item, index) => this.getRectByDom(this.$refs[`uv-swipe-action-item__right__button-${index}`][0]))
|
||||
// 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
|
||||
Promise.all(promiseAll).then((sizes) => {
|
||||
this.buttons = sizes
|
||||
// 计算所有按钮总宽度
|
||||
this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
|
||||
})
|
||||
},
|
||||
// 通过nvue的dom模块,查询节点信息
|
||||
getRectByDom(ref) {
|
||||
return new Promise((resolve) => {
|
||||
dom.getComponentRect(ref, (res) => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
// nvue操作dom的库,用于获取dom的尺寸信息
|
||||
const dom = uni.requireNativePlugin('dom');
|
||||
const bindingX = uni.requireNativePlugin('bindingx');
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
import { getDuration, getPx } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 所有按钮的总宽度
|
||||
buttonsWidth: 0,
|
||||
// 是否正在移动中
|
||||
moving: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 获取过渡时间
|
||||
getDuratin() {
|
||||
let duration = String(this.duration)
|
||||
// 如果ms为单位,返回ms的数值部分
|
||||
if (duration.indexOf('ms') >= 0) return parseInt(duration)
|
||||
// 如果s为单位,为了得到ms的数值,需要乘以1000
|
||||
if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
|
||||
// 如果值传了数值,且小于30,认为是s单位
|
||||
duration = Number(duration)
|
||||
return duration < 30 ? duration * 1000 : duration
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(n) {
|
||||
if(n) {
|
||||
this.moveCellByAnimation('open')
|
||||
} else {
|
||||
this.moveCellByAnimation('close')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(()=>{
|
||||
this.initialize()
|
||||
},20)
|
||||
},
|
||||
methods: {
|
||||
initialize() {
|
||||
this.queryRect()
|
||||
},
|
||||
// 关闭单元格,用于打开一个,自动关闭其他单元格的场景
|
||||
closeHandler() {
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
},
|
||||
// 点击单元格
|
||||
clickHandler() {
|
||||
// 如果在移动中被点击,进行忽略
|
||||
if(this.moving) return
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
},
|
||||
// 滑动单元格
|
||||
onTouchstart(e) {
|
||||
// 如果当前正在移动中,或者disabled状态,则返回
|
||||
if(this.moving || this.disabled) {
|
||||
return this.unbindBindingX()
|
||||
}
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
// 特殊情况下,e可能不为一个对象
|
||||
e?.stopPropagation && e.stopPropagation()
|
||||
e?.preventDefault && e.preventDefault()
|
||||
this.moving = true
|
||||
// 获取元素ref
|
||||
const content = this.getContentRef()
|
||||
let expression = `min(max(${-this.buttonsWidth}, x), 0)`
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
// 阿里为了KPI而开源的BindingX
|
||||
this.panEvent = bindingX.bind({
|
||||
anchor: content,
|
||||
eventType: 'pan',
|
||||
props: [{
|
||||
element: content,
|
||||
// 绑定width属性,设置其宽度值
|
||||
property: 'transform.translateX',
|
||||
expression
|
||||
}]
|
||||
}, (res) => {
|
||||
this.moving = false
|
||||
if (res.state === 'end' || res.state === 'exit') {
|
||||
const deltaX = res.deltaX
|
||||
if(deltaX <= -this.buttonsWidth || deltaX >= 0) {
|
||||
// 如果触摸滑动的过程中,大于单元格的总宽度,或者大于0,意味着已经动过滑动达到了打开或者关闭的状态
|
||||
// 这里直接进行状态的标记
|
||||
this.$nextTick(() => {
|
||||
this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close'
|
||||
})
|
||||
} else if(Math.abs(deltaX) > getPx(this.threshold)) {
|
||||
// 在移动大于阈值、并且小于总按钮宽度时,进行自动打开或者关闭
|
||||
// 移动距离大于0时,意味着需要关闭状态
|
||||
if(Math.abs(deltaX) < this.buttonsWidth) {
|
||||
this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open')
|
||||
}
|
||||
} else {
|
||||
// 在小于阈值时,进行关闭操作(如果在打开状态下,将不会执行bindingX)
|
||||
this.moveCellByAnimation('close')
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 释放bindingX
|
||||
unbindBindingX() {
|
||||
// 释放上一次的资源
|
||||
if (this?.panEvent?.token != 0) {
|
||||
bindingX.unbind({
|
||||
token: this.panEvent?.token,
|
||||
// pan为手势事件
|
||||
eventType: 'pan'
|
||||
})
|
||||
}
|
||||
},
|
||||
// 查询按钮节点信息
|
||||
queryRect() {
|
||||
// 历遍所有按钮数组,通过getRectByDom返回一个promise
|
||||
const promiseAll = this.options.map(async(item, index) => {
|
||||
return await this.getRectByDom(this.$refs[`uv-swipe-action-item__right__button-${index}`][0])
|
||||
})
|
||||
// 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
|
||||
Promise.all(promiseAll).then(sizes => {
|
||||
this.buttons = sizes
|
||||
// 计算所有按钮总宽度
|
||||
this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
|
||||
})
|
||||
},
|
||||
// 通过nvue的dom模块,查询节点信息
|
||||
getRectByDom(ref) {
|
||||
return new Promise(resolve => {
|
||||
dom.getComponentRect(ref, res => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 移动单元格到左边或者右边尽头
|
||||
moveCellByAnimation(status = 'open') {
|
||||
if(this.moving) return
|
||||
// 标识当前状态
|
||||
this.moveing = true
|
||||
const content = this.getContentRef()
|
||||
const x = status === 'open' ? -this.buttonsWidth : 0
|
||||
animation.transition(content, {
|
||||
styles: {
|
||||
transform: `translateX(${x}px)`,
|
||||
},
|
||||
duration: getDuration(this.duration, false),
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.moving = false
|
||||
this.status = status
|
||||
this.unbindBindingX()
|
||||
})
|
||||
},
|
||||
// 获取元素ref
|
||||
getContentRef() {
|
||||
return this.$refs['uv-swipe-action-item__content'].ref
|
||||
}
|
||||
},
|
||||
// #ifdef VUE2
|
||||
beforeDestroy() {
|
||||
this.unbindBindingX()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
this.unbindBindingX()
|
||||
}
|
||||
// #endif
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
export default {
|
||||
props: {
|
||||
// 控制打开或者关闭
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 标识符,如果是v-for,可用index索引值
|
||||
name: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否自动关闭其他swipe按钮组
|
||||
autoClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 滑动距离阈值,只有大于此值,才被认为是要打开菜单
|
||||
threshold: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
// 右侧按钮内容
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 动画过渡时间,单位ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
...uni.$uv?.props?.swipeActionItem
|
||||
}
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
<template>
|
||||
<view class="uv-swipe-action-item" ref="uv-swipe-action-item">
|
||||
<view class="uv-swipe-action-item__right">
|
||||
<slot name="button">
|
||||
<view v-for="(item,index) in options" :key="index" class="uv-swipe-action-item__right__button"
|
||||
:ref="`uv-swipe-action-item__right__button-${index}`" :style="[{
|
||||
alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch'
|
||||
}]" @tap="buttonClickHandler(item, index)">
|
||||
<view class="uv-swipe-action-item__right__button__wrapper" :style="[{
|
||||
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
|
||||
borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0',
|
||||
padding: item.style && item.style.borderRadius ? '0' : '0 15px',
|
||||
}, item.style]">
|
||||
<uv-icon v-if="item.icon" :name="item.icon"
|
||||
:color="item.style && item.style.color ? item.style.color : '#ffffff'"
|
||||
:size="item.iconSize ? $uv.addUnit(item.iconSize) : item.style && item.style.fontSize ? $uv.getPx(item.style.fontSize) * 1.2 : 17"
|
||||
:customStyle="{
|
||||
marginRight: item.text ? '2px' : 0
|
||||
}"></uv-icon>
|
||||
<text v-if="item.text" class="uv-swipe-action-item__right__button__wrapper__text uv-line-1"
|
||||
:style="[{
|
||||
color: item.style && item.style.color ? item.style.color : '#ffffff',
|
||||
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px',
|
||||
lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px',
|
||||
}]">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="uv-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove"
|
||||
@touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size"
|
||||
:change:size="wxs.sizeChange">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="uv-swipe-action-item__content" ref="uv-swipe-action-item__content" @panstart="onTouchstart"
|
||||
@tap="clickHandler">
|
||||
<!-- #endif -->
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
|
||||
<script src="./index.wxs" module="wxs" lang="wxs"></script>
|
||||
<!-- #endif -->
|
||||
<script>
|
||||
import touch from '@/uni_modules/uv-ui-tools/libs/mixin/touch.js'
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
import nvue from './nvue.js';
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
|
||||
import wxs from './wxs.js';
|
||||
// #endif
|
||||
/**
|
||||
* SwipeActionItem 滑动单元格子组件
|
||||
* @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
|
||||
* @tutorial https://www.uvui.cn/components/swipeAction.html
|
||||
* @property {Boolean} show 控制打开或者关闭(默认 false )
|
||||
* @property {String | Number} index 标识符,如果是v-for,可用index索引
|
||||
* @property {Boolean} disabled 是否禁用(默认 false )
|
||||
* @property {Boolean} autoClose 是否自动关闭其他swipe按钮组(默认 true )
|
||||
* @property {Number} threshold 滑动距离阈值,只有大于此值,才被认为是要打开菜单(默认 30 )
|
||||
* @property {Array} options 右侧按钮内容
|
||||
* @property {String | Number} duration 动画过渡时间,单位ms(默认 350 )
|
||||
* @event {Function(index)} open 组件打开时触发
|
||||
* @event {Function(index)} close 组件关闭时触发
|
||||
* @example <uv-swipe-action><uv-swipe-action-item :options="options1" ></uv-swipe-action-item></uv-swipe-action>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swipe-action-item',
|
||||
emits: ['click'],
|
||||
// #ifndef APP-NVUE
|
||||
mixins: [mpMixin, mixin, props, touch],
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
mixins: [mpMixin, mixin, props, nvue , touch],
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
|
||||
mixins: [mpMixin, mixin, props, touch, wxs],
|
||||
// #endif
|
||||
data() {
|
||||
return {
|
||||
// 按钮的尺寸信息
|
||||
size: {},
|
||||
// 父组件uv-swipe-action的参数
|
||||
parentData: {
|
||||
autoClose: true,
|
||||
},
|
||||
// 当前状态,open-打开,close-关闭
|
||||
status: 'close',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 由于wxs无法直接读取外部的值,需要在外部值变化时,重新执行赋值逻辑
|
||||
wxsInit(newValue, oldValue) {
|
||||
this.queryRect()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wxsInit() {
|
||||
return [this.disabled, this.autoClose, this.threshold, this.options, this.duration]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef MP-TOUTIAO
|
||||
this.$uv.error('抖音小程序暂不支持wxs,故该组件暂不支持抖音小程序');
|
||||
// #endif
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 初始化父组件数据
|
||||
this.updateParentData()
|
||||
// #ifndef APP-NVUE
|
||||
this.$uv.sleep().then(() => {
|
||||
this.queryRect()
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
updateParentData() {
|
||||
// 此方法在mixin中
|
||||
this.getParentData('uv-swipe-action')
|
||||
},
|
||||
// #ifndef APP-NVUE
|
||||
// 查询节点
|
||||
queryRect() {
|
||||
this.$uvGetRect('.uv-swipe-action-item__right__button', true).then(buttons => {
|
||||
this.size = {
|
||||
buttons,
|
||||
show: this.show,
|
||||
disabled: this.disabled,
|
||||
threshold: this.threshold,
|
||||
duration: this.duration
|
||||
}
|
||||
})
|
||||
},
|
||||
// #endif
|
||||
// 按钮被点击
|
||||
buttonClickHandler(item, index) {
|
||||
this.$emit('click', {
|
||||
index,
|
||||
name: this.name
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
|
||||
.uv-swipe-action-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* #ifndef APP-NVUE || MP-WEIXIN */
|
||||
touch-action: pan-y;
|
||||
/* #endif */
|
||||
|
||||
&__content {
|
||||
background-color: #FFFFFF;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
@include flex;
|
||||
|
||||
&__button {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
|
||||
&__wrapper {
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 15px;
|
||||
|
||||
&__text {
|
||||
@include flex;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,15 @@
|
|||
export default {
|
||||
methods: {
|
||||
// 关闭时执行
|
||||
closeHandler() {
|
||||
this.status = 'close'
|
||||
},
|
||||
setState(status) {
|
||||
this.status = status
|
||||
},
|
||||
closeOther() {
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export default {
|
||||
props: {
|
||||
// 是否自动关闭其他swipe按钮组
|
||||
autoClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
...uni.$uv?.props?.swipeAction
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<template>
|
||||
<view class="uv-swipe-action">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* SwipeAction 滑动单元格
|
||||
* @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
|
||||
* @tutorial https://www.uvui.cn/components/swipeAction.html
|
||||
* @property {Boolean} autoClose 是否自动关闭其他swipe按钮组
|
||||
* @event {Function(index)} click 点击组件时触发
|
||||
* @example <uv-swipe-action><uv-swipe-action-item :rightOptions="options1" ></uv-swipe-action-item></uv-swipe-action>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swipe-action',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
swipeAction: this
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 这里computed的变量,都是子组件uv-swipe-action-item需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
|
||||
// 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(uv-swipe-action-item)
|
||||
// 拉取父组件新的变化后的参数
|
||||
parentData() {
|
||||
return [this.autoClose]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
|
||||
parentData() {
|
||||
if (this.children.length) {
|
||||
this.children.map(child => {
|
||||
// 判断子组件(uv-swipe-action-item)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
|
||||
typeof(child.updateParentData) === 'function' && child.updateParentData()
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.children = []
|
||||
},
|
||||
methods: {
|
||||
closeOther(child) {
|
||||
if (this.autoClose) {
|
||||
// 历遍所有的单元格,找出非当前操作中的单元格,进行关闭
|
||||
this.children.map((item, index) => {
|
||||
if (child !== item) {
|
||||
item.closeHandler()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
"id": "uv-swipe-action",
|
||||
"displayName": "uv-swipe-action 滑动单元格 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.4",
|
||||
"description": "滑动单元格组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作。",
|
||||
"keywords": [
|
||||
"uv-swipe-action",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"swipe-action",
|
||||
"滑动单元格"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"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",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
## SwipeAction 滑动单元格
|
||||
|
||||
> **组件名:uv-swipe-action**
|
||||
|
||||
该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/swipeAction.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
|
@ -0,0 +1,66 @@
|
|||
## 1.1.20(2023-10-30)
|
||||
1. 1.1.16版本
|
||||
## 1.1.19(2023-10-13)
|
||||
1. 兼容vue3
|
||||
## 1.1.18(2023-10-12)
|
||||
1. 1.1.15版本
|
||||
## 1.1.17(2023-09-27)
|
||||
1. 1.1.14版本发布
|
||||
## 1.1.16(2023-09-15)
|
||||
1. 1.1.13版本发布
|
||||
## 1.1.15(2023-09-15)
|
||||
1. 更新button.js相关按钮支持open-type="agreePrivacyAuthorization"
|
||||
## 1.1.14(2023-09-14)
|
||||
1. 优化dayjs
|
||||
## 1.1.13(2023-09-13)
|
||||
1. 优化,$uv中增加unit参数,方便组件中使用
|
||||
## 1.1.12(2023-09-10)
|
||||
1. 升级版本
|
||||
## 1.1.11(2023-09-04)
|
||||
1. 1.1.11版本
|
||||
## 1.1.10(2023-08-31)
|
||||
1. 修复customStyle和customClass存在冲突的问题
|
||||
## 1.1.9(2023-08-27)
|
||||
1. 版本升级
|
||||
2. 优化
|
||||
## 1.1.8(2023-08-24)
|
||||
1. 版本升级
|
||||
## 1.1.7(2023-08-22)
|
||||
1. 版本升级
|
||||
## 1.1.6(2023-08-18)
|
||||
uvui版本:1.1.6
|
||||
## 1.0.15(2023-08-14)
|
||||
1. 更新uvui版本号
|
||||
## 1.0.13(2023-08-06)
|
||||
1. 优化
|
||||
## 1.0.12(2023-08-06)
|
||||
1. 修改版本号
|
||||
## 1.0.11(2023-08-06)
|
||||
1. 路由增加events参数
|
||||
2. 路由拦截修复
|
||||
## 1.0.10(2023-08-01)
|
||||
1. 优化
|
||||
## 1.0.9(2023-06-28)
|
||||
优化openType.js
|
||||
## 1.0.8(2023-06-15)
|
||||
1. 修改支付宝报错的BUG
|
||||
## 1.0.7(2023-06-07)
|
||||
1. 解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
|
||||
2. 解决上述提示,需要在uni.scss配置$uvui-nvue-style: false; 然后在APP.vue下面引入uvui内置的基础样式:@import '@/uni_modules/uv-ui-tools/index.scss';
|
||||
## 1.0.6(2023-06-04)
|
||||
1. uv-ui-tools 优化工具组件,兼容更多功能
|
||||
2. 小程序分享功能优化等
|
||||
## 1.0.5(2023-06-02)
|
||||
1. 修改扩展使用mixin中方法的问题
|
||||
## 1.0.4(2023-05-23)
|
||||
1. 兼容百度小程序修改bem函数
|
||||
## 1.0.3(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.2(2023-05-10)
|
||||
1. 增加Http请求封装
|
||||
2. 优化
|
||||
## 1.0.1(2023-05-04)
|
||||
1. 修改名称及备注
|
||||
## 1.0.0(2023-05-04)
|
||||
1. uv-ui工具集首次发布
|
|
@ -0,0 +1,6 @@
|
|||
<template>
|
||||
</template>
|
||||
<script>
|
||||
</script>
|
||||
<style>
|
||||
</style>
|
|
@ -0,0 +1,79 @@
|
|||
// 全局挂载引入http相关请求拦截插件
|
||||
import Request from './libs/luch-request'
|
||||
|
||||
// 引入全局mixin
|
||||
import mixin from './libs/mixin/mixin.js'
|
||||
// 小程序特有的mixin
|
||||
import mpMixin from './libs/mixin/mpMixin.js'
|
||||
// #ifdef MP
|
||||
import mpShare from '@/uni_modules/uv-ui-tools/libs/mixin/mpShare.js'
|
||||
// #endif
|
||||
|
||||
// 路由封装
|
||||
import route from './libs/util/route.js'
|
||||
// 公共工具函数
|
||||
import * as index from './libs/function/index.js'
|
||||
// 防抖方法
|
||||
import debounce from './libs/function/debounce.js'
|
||||
// 节流方法
|
||||
import throttle from './libs/function/throttle.js'
|
||||
// 规则检验
|
||||
import * as test from './libs/function/test.js'
|
||||
|
||||
// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
|
||||
import * as colorGradient from './libs/function/colorGradient.js'
|
||||
|
||||
// 配置信息
|
||||
import config from './libs/config/config.js'
|
||||
// 平台
|
||||
import platform from './libs/function/platform'
|
||||
|
||||
const $uv = {
|
||||
route,
|
||||
config,
|
||||
test,
|
||||
date: index.timeFormat, // 另名date
|
||||
...index,
|
||||
colorGradient: colorGradient.colorGradient,
|
||||
hexToRgb: colorGradient.hexToRgb,
|
||||
rgbToHex: colorGradient.rgbToHex,
|
||||
colorToRgba: colorGradient.colorToRgba,
|
||||
http: new Request(),
|
||||
debounce,
|
||||
throttle,
|
||||
platform,
|
||||
mixin,
|
||||
mpMixin
|
||||
}
|
||||
uni.$uv = $uv;
|
||||
const install = (Vue,options={}) => {
|
||||
// #ifndef APP-NVUE
|
||||
const cloneMixin = index.deepClone(mixin);
|
||||
delete cloneMixin?.props?.customClass;
|
||||
delete cloneMixin?.props?.customStyle;
|
||||
Vue.mixin(cloneMixin);
|
||||
// #ifdef MP
|
||||
if(options.mpShare){
|
||||
Vue.mixin(mpShare);
|
||||
}
|
||||
// #endif
|
||||
// #endif
|
||||
// #ifdef VUE2
|
||||
// 时间格式化,同时两个名称,date和timeFormat
|
||||
Vue.filter('timeFormat', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
|
||||
Vue.filter('date', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
|
||||
// 将多久以前的方法,注入到全局过滤器
|
||||
Vue.filter('timeFrom', (timestamp, format) => uni.$uv.timeFrom(timestamp, format));
|
||||
// 同时挂载到uni和Vue.prototype中
|
||||
// #ifndef APP-NVUE
|
||||
// 只有vue,挂载到Vue.prototype才有意义,因为nvue中全局Vue.prototype和Vue.mixin是无效的
|
||||
Vue.prototype.$uv = $uv;
|
||||
// #endif
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
Vue.config.globalProperties.$uv = $uv;
|
||||
// #endif
|
||||
}
|
||||
export default {
|
||||
install
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// 引入公共基础类
|
||||
@import "./libs/css/common.scss";
|
||||
|
||||
// 非nvue的样式
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "./libs/css/vue.scss";
|
||||
/* #endif */
|
|
@ -0,0 +1,34 @@
|
|||
// 此版本发布于2023-10-30
|
||||
const version = '1.1.16'
|
||||
|
||||
// 开发环境才提示,生产环境不会提示
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log(`\n %c uvui V${version} https://www.uvui.cn/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;');
|
||||
}
|
||||
|
||||
export default {
|
||||
v: version,
|
||||
version,
|
||||
// 主题名称
|
||||
type: [
|
||||
'primary',
|
||||
'success',
|
||||
'info',
|
||||
'error',
|
||||
'warning'
|
||||
],
|
||||
// 颜色部分,本来可以通过scss的:export导出供js使用,但是奈何nvue不支持
|
||||
color: {
|
||||
'uv-primary': '#2979ff',
|
||||
'uv-warning': '#ff9900',
|
||||
'uv-success': '#19be6b',
|
||||
'uv-error': '#fa3534',
|
||||
'uv-info': '#909399',
|
||||
'uv-main-color': '#303133',
|
||||
'uv-content-color': '#606266',
|
||||
'uv-tips-color': '#909399',
|
||||
'uv-light-color': '#c0c4cc'
|
||||
},
|
||||
// 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
|
||||
unit: 'px'
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
$uv-main-color: #303133 !default;
|
||||
$uv-content-color: #606266 !default;
|
||||
$uv-tips-color: #909193 !default;
|
||||
$uv-light-color: #c0c4cc !default;
|
||||
$uv-border-color: #dadbde !default;
|
||||
$uv-bg-color: #f3f4f6 !default;
|
||||
$uv-disabled-color: #c8c9cc !default;
|
||||
|
||||
$uv-primary: #3c9cff !default;
|
||||
$uv-primary-dark: #398ade !default;
|
||||
$uv-primary-disabled: #9acafc !default;
|
||||
$uv-primary-light: #ecf5ff !default;
|
||||
|
||||
$uv-warning: #f9ae3d !default;
|
||||
$uv-warning-dark: #f1a532 !default;
|
||||
$uv-warning-disabled: #f9d39b !default;
|
||||
$uv-warning-light: #fdf6ec !default;
|
||||
|
||||
$uv-success: #5ac725 !default;
|
||||
$uv-success-dark: #53c21d !default;
|
||||
$uv-success-disabled: #a9e08f !default;
|
||||
$uv-success-light: #f5fff0;
|
||||
|
||||
$uv-error: #f56c6c !default;
|
||||
$uv-error-dark: #e45656 !default;
|
||||
$uv-error-disabled: #f7b2b2 !default;
|
||||
$uv-error-light: #fef0f0 !default;
|
||||
|
||||
$uv-info: #909399 !default;
|
||||
$uv-info-dark: #767a82 !default;
|
||||
$uv-info-disabled: #c4c6c9 !default;
|
||||
$uv-info-light: #f4f4f5 !default;
|
|
@ -0,0 +1,100 @@
|
|||
// 超出行数,自动显示行尾省略号,最多5行
|
||||
// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
|
||||
@for $i from 1 through 5 {
|
||||
.uv-line-#{$i} {
|
||||
/* #ifdef APP-NVUE */
|
||||
// nvue下,可以直接使用lines属性,这是weex特有样式
|
||||
lines: $i;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// vue下,单行和多行显示省略号需要单独处理
|
||||
@if $i == '1' {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box!important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical!important;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
$uv-bordercolor: #dadbde;
|
||||
@if variable-exists(uv-border-color) {
|
||||
$uv-bordercolor: $uv-border-color;
|
||||
}
|
||||
|
||||
// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
|
||||
// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
|
||||
// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
|
||||
// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
|
||||
.uv-border {
|
||||
border-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-top {
|
||||
border-top-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-left {
|
||||
border-left-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-right {
|
||||
border-right-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-right-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-bottom {
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
.uv-border-top-bottom {
|
||||
border-top-width: 0.5px!important;
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
|
||||
.uv-reset-button {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
/* #ifndef APP-PLUS */
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-width: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uv-reset-button::after {
|
||||
border: none;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.uv-hover-class {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
@mixin flex($direction: row) {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: $direction;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// 由于uvui是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
|
||||
// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
|
||||
$uvui-nvue-style: true !default;
|
||||
@if $uvui-nvue-style == true {
|
||||
view, scroll-view, swiper-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: auto;
|
||||
align-items: stretch;
|
||||
align-content: flex-start;
|
||||
}
|
||||
}
|
||||
/* #endif */
|
|
@ -0,0 +1,111 @@
|
|||
// 超出行数,自动显示行尾省略号,最多5行
|
||||
// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
|
||||
@if variable-exists(show-lines) {
|
||||
@for $i from 1 through 5 {
|
||||
.uv-line-#{$i} {
|
||||
/* #ifdef APP-NVUE */
|
||||
// nvue下,可以直接使用lines属性,这是weex特有样式
|
||||
lines: $i;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// vue下,单行和多行显示省略号需要单独处理
|
||||
@if $i == '1' {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
} @else {
|
||||
display: -webkit-box!important;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
-webkit-line-clamp: $i;
|
||||
-webkit-box-orient: vertical!important;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border) {
|
||||
$uv-bordercolor: #dadbde;
|
||||
@if variable-exists(uv-border-color) {
|
||||
$uv-bordercolor: $uv-border-color;
|
||||
}
|
||||
// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
|
||||
// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
|
||||
// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
|
||||
// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
|
||||
@if variable-exists(show-border-surround) {
|
||||
.uv-border {
|
||||
border-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-top) {
|
||||
.uv-border-top {
|
||||
border-top-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-left) {
|
||||
.uv-border-left {
|
||||
border-left-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-left-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-right) {
|
||||
.uv-border-right {
|
||||
border-right-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-right-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-bottom) {
|
||||
.uv-border-bottom {
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-border-top-bottom) {
|
||||
.uv-border-top-bottom {
|
||||
border-top-width: 0.5px!important;
|
||||
border-bottom-width: 0.5px!important;
|
||||
border-color: $uv-bordercolor!important;
|
||||
border-top-style: solid;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@if variable-exists(show-reset-button) {
|
||||
// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
|
||||
.uv-reset-button {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
/* #ifndef APP-PLUS */
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
/* #endif */
|
||||
/* #ifdef APP-NVUE */
|
||||
border-width: 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uv-reset-button::after {
|
||||
border: none;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
@if variable-exists(show-hover) {
|
||||
.uv-hover-class {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
// 历遍生成4个方向的底部安全区
|
||||
@each $d in top, right, bottom, left {
|
||||
.uv-safe-area-inset-#{$d} {
|
||||
padding-#{$d}: 0;
|
||||
padding-#{$d}: constant(safe-area-inset-#{$d});
|
||||
padding-#{$d}: env(safe-area-inset-#{$d});
|
||||
}
|
||||
}
|
||||
|
||||
//提升H5端uni.toast()的层级,避免被uvui的modal等遮盖
|
||||
/* #ifdef H5 */
|
||||
uni-toast {
|
||||
z-index: 10090;
|
||||
}
|
||||
uni-toast .uni-toast {
|
||||
z-index: 10090;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
// 隐藏scroll-view的滚动条
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
$uvui-nvue-style: true !default;
|
||||
@if $uvui-nvue-style == false {
|
||||
view, scroll-view, swiper-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: auto;
|
||||
align-items: stretch;
|
||||
align-content: flex-start;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* 求两个颜色之间的渐变值
|
||||
* @param {string} startColor 开始的颜色
|
||||
* @param {string} endColor 结束的颜色
|
||||
* @param {number} step 颜色等分的份额
|
||||
* */
|
||||
function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
|
||||
const startRGB = hexToRgb(startColor, false) // 转换为rgb数组模式
|
||||
const startR = startRGB[0]
|
||||
const startG = startRGB[1]
|
||||
const startB = startRGB[2]
|
||||
|
||||
const endRGB = hexToRgb(endColor, false)
|
||||
const endR = endRGB[0]
|
||||
const endG = endRGB[1]
|
||||
const endB = endRGB[2]
|
||||
|
||||
const sR = (endR - startR) / step // 总差值
|
||||
const sG = (endG - startG) / step
|
||||
const sB = (endB - startB) / step
|
||||
const colorArr = []
|
||||
for (let i = 0; i < step; i++) {
|
||||
// 计算每一步的hex值
|
||||
let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
|
||||
* i + startB))})`)
|
||||
// 确保第一个颜色值为startColor的值
|
||||
if (i === 0) hex = rgbToHex(startColor)
|
||||
// 确保最后一个颜色值为endColor的值
|
||||
if (i === step - 1) hex = rgbToHex(endColor)
|
||||
colorArr.push(hex)
|
||||
}
|
||||
return colorArr
|
||||
}
|
||||
|
||||
// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
|
||||
function hexToRgb(sColor, str = true) {
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
sColor = String(sColor).toLowerCase()
|
||||
if (sColor && reg.test(sColor)) {
|
||||
if (sColor.length === 4) {
|
||||
let sColorNew = '#'
|
||||
for (let i = 1; i < 4; i += 1) {
|
||||
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
|
||||
}
|
||||
sColor = sColorNew
|
||||
}
|
||||
// 处理六位的颜色值
|
||||
const sColorChange = []
|
||||
for (let i = 1; i < 7; i += 2) {
|
||||
sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
|
||||
}
|
||||
if (!str) {
|
||||
return sColorChange
|
||||
}
|
||||
return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
|
||||
} if (/^(rgb|RGB)/.test(sColor)) {
|
||||
const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
|
||||
return arr.map((val) => Number(val))
|
||||
}
|
||||
return sColor
|
||||
}
|
||||
|
||||
// 将rgb表示方式转换为hex表示方式
|
||||
function rgbToHex(rgb) {
|
||||
const _this = rgb
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
if (/^(rgb|RGB)/.test(_this)) {
|
||||
const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
|
||||
let strHex = '#'
|
||||
for (let i = 0; i < aColor.length; i++) {
|
||||
let hex = Number(aColor[i]).toString(16)
|
||||
hex = String(hex).length == 1 ? `${0}${hex}` : hex // 保证每个rgb的值为2位
|
||||
if (hex === '0') {
|
||||
hex += hex
|
||||
}
|
||||
strHex += hex
|
||||
}
|
||||
if (strHex.length !== 7) {
|
||||
strHex = _this
|
||||
}
|
||||
return strHex
|
||||
} if (reg.test(_this)) {
|
||||
const aNum = _this.replace(/#/, '').split('')
|
||||
if (aNum.length === 6) {
|
||||
return _this
|
||||
} if (aNum.length === 3) {
|
||||
let numHex = '#'
|
||||
for (let i = 0; i < aNum.length; i += 1) {
|
||||
numHex += (aNum[i] + aNum[i])
|
||||
}
|
||||
return numHex
|
||||
}
|
||||
} else {
|
||||
return _this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
|
||||
* sHex为传入的十六进制的色值
|
||||
* alpha为rgba的透明度
|
||||
*/
|
||||
function colorToRgba(color, alpha) {
|
||||
color = rgbToHex(color)
|
||||
// 十六进制颜色值的正则表达式
|
||||
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
|
||||
/* 16进制颜色转为RGB格式 */
|
||||
let sColor = String(color).toLowerCase()
|
||||
if (sColor && reg.test(sColor)) {
|
||||
if (sColor.length === 4) {
|
||||
let sColorNew = '#'
|
||||
for (let i = 1; i < 4; i += 1) {
|
||||
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
|
||||
}
|
||||
sColor = sColorNew
|
||||
}
|
||||
// 处理六位的颜色值
|
||||
const sColorChange = []
|
||||
for (let i = 1; i < 7; i += 2) {
|
||||
sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
|
||||
}
|
||||
// return sColorChange.join(',')
|
||||
return `rgba(${sColorChange.join(',')},${alpha})`
|
||||
}
|
||||
|
||||
return sColor
|
||||
}
|
||||
|
||||
export {
|
||||
colorGradient,
|
||||
hexToRgb,
|
||||
rgbToHex,
|
||||
colorToRgba
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
let timeout = null
|
||||
|
||||
/**
|
||||
* 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
|
||||
*
|
||||
* @param {Function} func 要执行的回调函数
|
||||
* @param {Number} wait 延时的时间
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
* @return null
|
||||
*/
|
||||
function debounce(func, wait = 500, immediate = false) {
|
||||
// 清除定时器
|
||||
if (timeout !== null) clearTimeout(timeout)
|
||||
// 立即执行,此类情况一般用不到
|
||||
if (immediate) {
|
||||
const callNow = !timeout
|
||||
timeout = setTimeout(() => {
|
||||
timeout = null
|
||||
}, wait)
|
||||
if (callNow) typeof func === 'function' && func()
|
||||
} else {
|
||||
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
|
||||
timeout = setTimeout(() => {
|
||||
typeof func === 'function' && func()
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
|
||||
export default debounce
|
|
@ -0,0 +1,167 @@
|
|||
let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
|
||||
|
||||
/**
|
||||
* 把错误的数据转正
|
||||
* @private
|
||||
* @example strip(0.09999999999999998)=0.1
|
||||
*/
|
||||
function strip(num, precision = 15) {
|
||||
return +parseFloat(Number(num).toPrecision(precision));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return digits length of a number
|
||||
* @private
|
||||
* @param {*number} num Input number
|
||||
*/
|
||||
function digitLength(num) {
|
||||
// Get digit length of e
|
||||
const eSplit = num.toString().split(/[eE]/);
|
||||
const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
|
||||
return len > 0 ? len : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把小数转成整数,如果是小数则放大成整数
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function float2Fixed(num) {
|
||||
if (num.toString().indexOf('e') === -1) {
|
||||
return Number(num.toString().replace('.', ''));
|
||||
}
|
||||
const dLen = digitLength(num);
|
||||
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数字是否越界,如果越界给出提示
|
||||
* @private
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function checkBoundary(num) {
|
||||
if (_boundaryCheckingState) {
|
||||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
|
||||
console.warn(`${num} 超出了精度限制,结果可能不正确`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 把递归操作扁平迭代化
|
||||
* @param {number[]} arr 要操作的数字数组
|
||||
* @param {function} operation 迭代操作
|
||||
* @private
|
||||
*/
|
||||
function iteratorOperation(arr, operation) {
|
||||
const [num1, num2, ...others] = arr;
|
||||
let res = operation(num1, num2);
|
||||
|
||||
others.forEach((num) => {
|
||||
res = operation(res, num);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度乘法
|
||||
* @export
|
||||
*/
|
||||
export function times(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, times);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
const baseNum = digitLength(num1) + digitLength(num2);
|
||||
const leftValue = num1Changed * num2Changed;
|
||||
|
||||
checkBoundary(leftValue);
|
||||
|
||||
return leftValue / Math.pow(10, baseNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度加法
|
||||
* @export
|
||||
*/
|
||||
export function plus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, plus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
// 取最大的小数位
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
// 把小数都转为整数然后再计算
|
||||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度减法
|
||||
* @export
|
||||
*/
|
||||
export function minus(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, minus);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
|
||||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 高精度除法
|
||||
* @export
|
||||
*/
|
||||
export function divide(...nums) {
|
||||
if (nums.length > 2) {
|
||||
return iteratorOperation(nums, divide);
|
||||
}
|
||||
|
||||
const [num1, num2] = nums;
|
||||
const num1Changed = float2Fixed(num1);
|
||||
const num2Changed = float2Fixed(num2);
|
||||
checkBoundary(num1Changed);
|
||||
checkBoundary(num2Changed);
|
||||
// 重要,这里必须用strip进行修正
|
||||
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
|
||||
}
|
||||
|
||||
/**
|
||||
* 四舍五入
|
||||
* @export
|
||||
*/
|
||||
export function round(num, ratio) {
|
||||
const base = Math.pow(10, ratio);
|
||||
let result = divide(Math.round(Math.abs(times(num, base))), base);
|
||||
if (num < 0 && result !== 0) {
|
||||
result = times(result, -1);
|
||||
}
|
||||
// 位数不足则补0
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否进行边界检查,默认开启
|
||||
* @param flag 标记开关,true 为开启,false 为关闭,默认为 true
|
||||
* @export
|
||||
*/
|
||||
export function enableBoundaryChecking(flag = true) {
|
||||
_boundaryCheckingState = flag;
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
times,
|
||||
plus,
|
||||
minus,
|
||||
divide,
|
||||
round,
|
||||
enableBoundaryChecking,
|
||||
};
|
||||
|
|
@ -0,0 +1,734 @@
|
|||
import { number, empty } from './test.js'
|
||||
import { round } from './digit.js'
|
||||
/**
|
||||
* @description 如果value小于min,取min;如果value大于max,取max
|
||||
* @param {number} min
|
||||
* @param {number} max
|
||||
* @param {number} value
|
||||
*/
|
||||
function range(min = 0, max = 0, value = 0) {
|
||||
return Math.max(min, Math.min(max, Number(value)))
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 用于获取用户传递值的px值 如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
|
||||
* @param {number|string} value 用户传递值的px值
|
||||
* @param {boolean} unit
|
||||
* @returns {number|string}
|
||||
*/
|
||||
function getPx(value, unit = false) {
|
||||
if (number(value)) {
|
||||
return unit ? `${value}px` : Number(value)
|
||||
}
|
||||
// 如果带有rpx,先取出其数值部分,再转为px值
|
||||
if (/(rpx|upx)$/.test(value)) {
|
||||
return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)))
|
||||
}
|
||||
return unit ? `${parseInt(value)}px` : parseInt(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 进行延时,以达到可以简写代码的目的 比如: await uni.$uv.sleep(20)将会阻塞20ms
|
||||
* @param {number} value 堵塞时间 单位ms 毫秒
|
||||
* @returns {Promise} 返回promise
|
||||
*/
|
||||
function sleep(value = 30) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve()
|
||||
}, value)
|
||||
})
|
||||
}
|
||||
/**
|
||||
* @description 运行期判断平台
|
||||
* @returns {string} 返回所在平台(小写)
|
||||
* @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
|
||||
*/
|
||||
function os() {
|
||||
return uni.getSystemInfoSync().platform.toLowerCase()
|
||||
}
|
||||
/**
|
||||
* @description 获取系统信息同步接口
|
||||
* @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
|
||||
*/
|
||||
function sys() {
|
||||
return uni.getSystemInfoSync()
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 取一个区间数
|
||||
* @param {Number} min 最小值
|
||||
* @param {Number} max 最大值
|
||||
*/
|
||||
function random(min, max) {
|
||||
if (min >= 0 && max > 0 && max >= min) {
|
||||
const gab = max - min + 1
|
||||
return Math.floor(Math.random() * gab + min)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Number} len uuid的长度
|
||||
* @param {Boolean} firstU 将返回的首字母置为"u"
|
||||
* @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
|
||||
*/
|
||||
function guid(len = 32, firstU = true, radix = null) {
|
||||
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
|
||||
const uuid = []
|
||||
radix = radix || chars.length
|
||||
|
||||
if (len) {
|
||||
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
|
||||
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
|
||||
} else {
|
||||
let r
|
||||
// rfc4122标准要求返回的uuid中,某些位为固定的字符
|
||||
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
|
||||
uuid[14] = '4'
|
||||
|
||||
for (let i = 0; i < 36; i++) {
|
||||
if (!uuid[i]) {
|
||||
r = 0 | Math.random() * 16
|
||||
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
|
||||
}
|
||||
}
|
||||
}
|
||||
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
|
||||
if (firstU) {
|
||||
uuid.shift()
|
||||
return `u${uuid.join('')}`
|
||||
}
|
||||
return uuid.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
|
||||
this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
|
||||
这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
|
||||
值(默认为undefined),就是查找最顶层的$parent
|
||||
* @param {string|undefined} name 父组件的参数名
|
||||
*/
|
||||
function $parent(name = undefined) {
|
||||
let parent = this.$parent
|
||||
// 通过while历遍,这里主要是为了H5需要多层解析的问题
|
||||
while (parent) {
|
||||
// 父组件
|
||||
if (parent.$options && parent.$options.name !== name) {
|
||||
// 如果组件的name不相等,继续上一级寻找
|
||||
parent = parent.$parent
|
||||
} else {
|
||||
return parent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 样式转换
|
||||
* 对象转字符串,或者字符串转对象
|
||||
* @param {object | string} customStyle 需要转换的目标
|
||||
* @param {String} target 转换的目的,object-转为对象,string-转为字符串
|
||||
* @returns {object|string}
|
||||
*/
|
||||
function addStyle(customStyle, target = 'object') {
|
||||
// 字符串转字符串,对象转对象情形,直接返回
|
||||
if (empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
|
||||
typeof(customStyle) === 'string') {
|
||||
return customStyle
|
||||
}
|
||||
// 字符串转对象
|
||||
if (target === 'object') {
|
||||
// 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
|
||||
customStyle = trim(customStyle)
|
||||
// 根据";"将字符串转为数组形式
|
||||
const styleArray = customStyle.split(';')
|
||||
const style = {}
|
||||
// 历遍数组,拼接成对象
|
||||
for (let i = 0; i < styleArray.length; i++) {
|
||||
// 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
|
||||
if (styleArray[i]) {
|
||||
const item = styleArray[i].split(':')
|
||||
style[trim(item[0])] = trim(item[1])
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
// 这里为对象转字符串形式
|
||||
let string = ''
|
||||
for (const i in customStyle) {
|
||||
// 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
|
||||
const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
string += `${key}:${customStyle[i]};`
|
||||
}
|
||||
// 去除两端空格
|
||||
return trim(string)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
|
||||
* @param {string|number} value 需要添加单位的值
|
||||
* @param {string} unit 添加的单位名 比如px
|
||||
*/
|
||||
function addUnit(value = 'auto', unit = uni?.$uv?.config?.unit ? uni?.$uv?.config?.unit : 'px') {
|
||||
value = String(value)
|
||||
// 用uvui内置验证规则中的number判断是否为数值
|
||||
return number(value) ? `${value}${unit}` : value
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 深度克隆
|
||||
* @param {object} obj 需要深度克隆的对象
|
||||
* @param cache 缓存
|
||||
* @returns {*} 克隆后的对象或者原值(不是对象)
|
||||
*/
|
||||
function deepClone(obj, cache = new WeakMap()) {
|
||||
if (obj === null || typeof obj !== 'object') return obj;
|
||||
if (cache.has(obj)) return cache.get(obj);
|
||||
let clone;
|
||||
if (obj instanceof Date) {
|
||||
clone = new Date(obj.getTime());
|
||||
} else if (obj instanceof RegExp) {
|
||||
clone = new RegExp(obj);
|
||||
} else if (obj instanceof Map) {
|
||||
clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
|
||||
} else if (obj instanceof Set) {
|
||||
clone = new Set(Array.from(obj, value => deepClone(value, cache)));
|
||||
} else if (Array.isArray(obj)) {
|
||||
clone = obj.map(value => deepClone(value, cache));
|
||||
} else if (Object.prototype.toString.call(obj) === '[object Object]') {
|
||||
clone = Object.create(Object.getPrototypeOf(obj));
|
||||
cache.set(obj, clone);
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
clone[key] = deepClone(value, cache);
|
||||
}
|
||||
} else {
|
||||
clone = Object.assign({}, obj);
|
||||
}
|
||||
cache.set(obj, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description JS对象深度合并
|
||||
* @param {object} target 需要拷贝的对象
|
||||
* @param {object} source 拷贝的来源对象
|
||||
* @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
|
||||
*/
|
||||
function deepMerge(target = {}, source = {}) {
|
||||
target = deepClone(target)
|
||||
if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
|
||||
const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
|
||||
for (const prop in source) {
|
||||
if (!source.hasOwnProperty(prop)) continue;
|
||||
const sourceValue = source[prop];
|
||||
const targetValue = merged[prop];
|
||||
if (sourceValue instanceof Date) {
|
||||
merged[prop] = new Date(sourceValue);
|
||||
} else if (sourceValue instanceof RegExp) {
|
||||
merged[prop] = new RegExp(sourceValue);
|
||||
} else if (sourceValue instanceof Map) {
|
||||
merged[prop] = new Map(sourceValue);
|
||||
} else if (sourceValue instanceof Set) {
|
||||
merged[prop] = new Set(sourceValue);
|
||||
} else if (typeof sourceValue === 'object' && sourceValue !== null) {
|
||||
merged[prop] = deepMerge(targetValue, sourceValue);
|
||||
} else {
|
||||
merged[prop] = sourceValue;
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description error提示
|
||||
* @param {*} err 错误内容
|
||||
*/
|
||||
function error(err) {
|
||||
// 开发环境才提示,生产环境不会提示
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.error(`uvui提示:${err}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 打乱数组
|
||||
* @param {array} array 需要打乱的数组
|
||||
* @returns {array} 打乱后的数组
|
||||
*/
|
||||
function randomArray(array = []) {
|
||||
// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
|
||||
return array.sort(() => Math.random() - 0.5)
|
||||
}
|
||||
|
||||
// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
|
||||
// 所以这里做一个兼容polyfill的兼容处理
|
||||
if (!String.prototype.padStart) {
|
||||
// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
|
||||
String.prototype.padStart = function(maxLength, fillString = ' ') {
|
||||
if (Object.prototype.toString.call(fillString) !== '[object String]') {
|
||||
throw new TypeError(
|
||||
'fillString must be String'
|
||||
)
|
||||
}
|
||||
const str = this
|
||||
// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
|
||||
if (str.length >= maxLength) return String(str)
|
||||
|
||||
const fillLength = maxLength - str.length
|
||||
let times = Math.ceil(fillLength / fillString.length)
|
||||
while (times >>= 1) {
|
||||
fillString += fillString
|
||||
if (times === 1) {
|
||||
fillString += fillString
|
||||
}
|
||||
}
|
||||
return fillString.slice(0, fillLength) + str
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 格式化时间
|
||||
* @param {String|Number} dateTime 需要格式化的时间戳
|
||||
* @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
|
||||
* @returns {string} 返回格式化后的字符串
|
||||
*/
|
||||
function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
|
||||
let date
|
||||
// 若传入时间为假值,则取当前时间
|
||||
if (!dateTime) {
|
||||
date = new Date()
|
||||
}
|
||||
// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
|
||||
else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
|
||||
date = new Date(dateTime * 1000)
|
||||
}
|
||||
// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
|
||||
else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
|
||||
date = new Date(Number(dateTime))
|
||||
}
|
||||
// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
|
||||
// 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
|
||||
else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
|
||||
date = new Date(dateTime.replace(/-/g, '/'))
|
||||
}
|
||||
// 其他都认为符合 RFC 2822 规范
|
||||
else {
|
||||
date = new Date(dateTime)
|
||||
}
|
||||
|
||||
const timeSource = {
|
||||
'y': date.getFullYear().toString(), // 年
|
||||
'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
|
||||
'd': date.getDate().toString().padStart(2, '0'), // 日
|
||||
'h': date.getHours().toString().padStart(2, '0'), // 时
|
||||
'M': date.getMinutes().toString().padStart(2, '0'), // 分
|
||||
's': date.getSeconds().toString().padStart(2, '0') // 秒
|
||||
// 有其他格式化字符需求可以继续添加,必须转化成字符串
|
||||
}
|
||||
|
||||
for (const key in timeSource) {
|
||||
const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
|
||||
if (ret) {
|
||||
// 年可能只需展示两位
|
||||
const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
|
||||
formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
|
||||
}
|
||||
}
|
||||
|
||||
return formatStr
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 时间戳转为多久之前
|
||||
* @param {String|Number} timestamp 时间戳
|
||||
* @param {String|Boolean} format
|
||||
* 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
|
||||
* 如果为布尔值false,无论什么时间,都返回多久以前的格式
|
||||
* @returns {string} 转化后的内容
|
||||
*/
|
||||
function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
|
||||
if (timestamp == null) timestamp = Number(new Date())
|
||||
timestamp = parseInt(timestamp)
|
||||
// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
|
||||
if (timestamp.toString().length == 10) timestamp *= 1000
|
||||
let timer = (new Date()).getTime() - timestamp
|
||||
timer = parseInt(timer / 1000)
|
||||
// 如果小于5分钟,则返回"刚刚",其他以此类推
|
||||
let tips = ''
|
||||
switch (true) {
|
||||
case timer < 300:
|
||||
tips = '刚刚'
|
||||
break
|
||||
case timer >= 300 && timer < 3600:
|
||||
tips = `${parseInt(timer / 60)}分钟前`
|
||||
break
|
||||
case timer >= 3600 && timer < 86400:
|
||||
tips = `${parseInt(timer / 3600)}小时前`
|
||||
break
|
||||
case timer >= 86400 && timer < 2592000:
|
||||
tips = `${parseInt(timer / 86400)}天前`
|
||||
break
|
||||
default:
|
||||
// 如果format为false,则无论什么时间戳,都显示xx之前
|
||||
if (format === false) {
|
||||
if (timer >= 2592000 && timer < 365 * 86400) {
|
||||
tips = `${parseInt(timer / (86400 * 30))}个月前`
|
||||
} else {
|
||||
tips = `${parseInt(timer / (86400 * 365))}年前`
|
||||
}
|
||||
} else {
|
||||
tips = timeFormat(timestamp, format)
|
||||
}
|
||||
}
|
||||
return tips
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 去除空格
|
||||
* @param String str 需要去除空格的字符串
|
||||
* @param String pos both(左右)|left|right|all 默认both
|
||||
*/
|
||||
function trim(str, pos = 'both') {
|
||||
str = String(str)
|
||||
if (pos == 'both') {
|
||||
return str.replace(/^\s+|\s+$/g, '')
|
||||
}
|
||||
if (pos == 'left') {
|
||||
return str.replace(/^\s*/, '')
|
||||
}
|
||||
if (pos == 'right') {
|
||||
return str.replace(/(\s*$)/g, '')
|
||||
}
|
||||
if (pos == 'all') {
|
||||
return str.replace(/\s+/g, '')
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 对象转url参数
|
||||
* @param {object} data,对象
|
||||
* @param {Boolean} isPrefix,是否自动加上"?"
|
||||
* @param {string} arrayFormat 规则 indices|brackets|repeat|comma
|
||||
*/
|
||||
function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
|
||||
const prefix = isPrefix ? '?' : ''
|
||||
const _result = []
|
||||
if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
|
||||
for (const key in data) {
|
||||
const value = data[key]
|
||||
// 去掉为空的参数
|
||||
if (['', undefined, null].indexOf(value) >= 0) {
|
||||
continue
|
||||
}
|
||||
// 如果值为数组,另行处理
|
||||
if (value.constructor === Array) {
|
||||
// e.g. {ids: [1, 2, 3]}
|
||||
switch (arrayFormat) {
|
||||
case 'indices':
|
||||
// 结果: ids[0]=1&ids[1]=2&ids[2]=3
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
_result.push(`${key}[${i}]=${value[i]}`)
|
||||
}
|
||||
break
|
||||
case 'brackets':
|
||||
// 结果: ids[]=1&ids[]=2&ids[]=3
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}[]=${_value}`)
|
||||
})
|
||||
break
|
||||
case 'repeat':
|
||||
// 结果: ids=1&ids=2&ids=3
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}=${_value}`)
|
||||
})
|
||||
break
|
||||
case 'comma':
|
||||
// 结果: ids=1,2,3
|
||||
let commaStr = ''
|
||||
value.forEach((_value) => {
|
||||
commaStr += (commaStr ? ',' : '') + _value
|
||||
})
|
||||
_result.push(`${key}=${commaStr}`)
|
||||
break
|
||||
default:
|
||||
value.forEach((_value) => {
|
||||
_result.push(`${key}[]=${_value}`)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
_result.push(`${key}=${value}`)
|
||||
}
|
||||
}
|
||||
return _result.length ? prefix + _result.join('&') : ''
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示消息提示框
|
||||
* @param {String} title 提示的内容,长度与 icon 取值有关。
|
||||
* @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
|
||||
*/
|
||||
function toast(title, duration = 2000) {
|
||||
uni.showToast({
|
||||
title: String(title),
|
||||
icon: 'none',
|
||||
duration
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 根据主题type值,获取对应的图标
|
||||
* @param {String} type 主题名称,primary|info|error|warning|success
|
||||
* @param {boolean} fill 是否使用fill填充实体的图标
|
||||
*/
|
||||
function type2icon(type = 'success', fill = false) {
|
||||
// 如果非预置值,默认为success
|
||||
if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'
|
||||
let iconName = ''
|
||||
// 目前(2019-12-12),info和primary使用同一个图标
|
||||
switch (type) {
|
||||
case 'primary':
|
||||
iconName = 'info-circle'
|
||||
break
|
||||
case 'info':
|
||||
iconName = 'info-circle'
|
||||
break
|
||||
case 'error':
|
||||
iconName = 'close-circle'
|
||||
break
|
||||
case 'warning':
|
||||
iconName = 'error-circle'
|
||||
break
|
||||
case 'success':
|
||||
iconName = 'checkmark-circle'
|
||||
break
|
||||
default:
|
||||
iconName = 'checkmark-circle'
|
||||
}
|
||||
// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
|
||||
if (fill) iconName += '-fill'
|
||||
return iconName
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 数字格式化
|
||||
* @param {number|string} number 要格式化的数字
|
||||
* @param {number} decimals 保留几位小数
|
||||
* @param {string} decimalPoint 小数点符号
|
||||
* @param {string} thousandsSeparator 千分位符号
|
||||
* @returns {string} 格式化后的数字
|
||||
*/
|
||||
function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
|
||||
number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
|
||||
const n = !isFinite(+number) ? 0 : +number
|
||||
const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
|
||||
const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
|
||||
const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
|
||||
let s = ''
|
||||
|
||||
s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
|
||||
const re = /(-?\d+)(\d{3})/
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, `$1${sep}$2`)
|
||||
}
|
||||
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || ''
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0')
|
||||
}
|
||||
return s.join(dec)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取duration值
|
||||
* 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
|
||||
* 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
|
||||
* @param {String|number} value 比如: "1s"|"100ms"|1|100
|
||||
* @param {boolean} unit 提示: 如果是false 默认返回number
|
||||
* @return {string|number}
|
||||
*/
|
||||
function getDuration(value, unit = true) {
|
||||
const valueNum = parseInt(value)
|
||||
if (unit) {
|
||||
if (/s$/.test(value)) return value
|
||||
return value > 30 ? `${value}ms` : `${value}s`
|
||||
}
|
||||
if (/ms$/.test(value)) return valueNum
|
||||
if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000
|
||||
return valueNum
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 日期的月或日补零操作
|
||||
* @param {String} value 需要补零的值
|
||||
*/
|
||||
function padZero(value) {
|
||||
return `00${value}`.slice(-2)
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 在uv-form的子组件内容发生变化,或者失去焦点时,尝试通知uv-form执行校验方法
|
||||
* @param {*} instance
|
||||
* @param {*} event
|
||||
*/
|
||||
function formValidate(instance, event) {
|
||||
const formItem = $parent.call(instance, 'uv-form-item')
|
||||
const form = $parent.call(instance, 'uv-form')
|
||||
// 如果发生变化的input或者textarea等,其父组件中有uv-form-item或者uv-form等,就执行form的validate方法
|
||||
// 同时将form-item的pros传递给form,让其进行精确对象验证
|
||||
if (formItem && form) {
|
||||
form.validateField(formItem.prop, () => {}, event)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
|
||||
* @param {object} obj 对象
|
||||
* @param {string} key 需要获取的属性字段
|
||||
* @returns {*}
|
||||
*/
|
||||
function getProperty(obj, key) {
|
||||
if (!obj) {
|
||||
return
|
||||
}
|
||||
if (typeof key !== 'string' || key === '') {
|
||||
return ''
|
||||
}
|
||||
if (key.indexOf('.') !== -1) {
|
||||
const keys = key.split('.')
|
||||
let firstObj = obj[keys[0]] || {}
|
||||
|
||||
for (let i = 1; i < keys.length; i++) {
|
||||
if (firstObj) {
|
||||
firstObj = firstObj[keys[i]]
|
||||
}
|
||||
}
|
||||
return firstObj
|
||||
}
|
||||
return obj[key]
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 设置对象的属性值,如果'a.b.c'的形式进行设置
|
||||
* @param {object} obj 对象
|
||||
* @param {string} key 需要设置的属性
|
||||
* @param {string} value 设置的值
|
||||
*/
|
||||
function setProperty(obj, key, value) {
|
||||
if (!obj) {
|
||||
return
|
||||
}
|
||||
// 递归赋值
|
||||
const inFn = function(_obj, keys, v) {
|
||||
// 最后一个属性key
|
||||
if (keys.length === 1) {
|
||||
_obj[keys[0]] = v
|
||||
return
|
||||
}
|
||||
// 0~length-1个key
|
||||
while (keys.length > 1) {
|
||||
const k = keys[0]
|
||||
if (!_obj[k] || (typeof _obj[k] !== 'object')) {
|
||||
_obj[k] = {}
|
||||
}
|
||||
const key = keys.shift()
|
||||
// 自调用判断是否存在属性,不存在则自动创建对象
|
||||
inFn(_obj[k], keys, v)
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof key !== 'string' || key === '') {
|
||||
|
||||
} else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
|
||||
const keys = key.split('.')
|
||||
inFn(obj, keys, value)
|
||||
} else {
|
||||
obj[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取当前页面路径
|
||||
*/
|
||||
function page() {
|
||||
const pages = getCurrentPages();
|
||||
const route = pages[pages.length - 1]?.route;
|
||||
// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
|
||||
return `/${route ? route : ''}`
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 获取当前路由栈实例数组
|
||||
*/
|
||||
function pages() {
|
||||
const pages = getCurrentPages()
|
||||
return pages
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取页面历史栈指定层实例
|
||||
* @param back {number} [0] - 0或者负数,表示获取历史栈的哪一层,0表示获取当前页面实例,-1 表示获取上一个页面实例。默认0。
|
||||
*/
|
||||
function getHistoryPage(back = 0) {
|
||||
const pages = getCurrentPages()
|
||||
const len = pages.length
|
||||
return pages[len - 1 + back]
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @description 修改uvui内置属性值
|
||||
* @param {object} props 修改内置props属性
|
||||
* @param {object} config 修改内置config属性
|
||||
* @param {object} color 修改内置color属性
|
||||
* @param {object} zIndex 修改内置zIndex属性
|
||||
*/
|
||||
function setConfig({
|
||||
props = {},
|
||||
config = {},
|
||||
color = {},
|
||||
zIndex = {}
|
||||
}) {
|
||||
const {
|
||||
deepMerge,
|
||||
} = uni.$uv
|
||||
uni.$uv.config = deepMerge(uni.$uv.config, config)
|
||||
uni.$uv.props = deepMerge(uni.$uv.props, props)
|
||||
uni.$uv.color = deepMerge(uni.$uv.color, color)
|
||||
uni.$uv.zIndex = deepMerge(uni.$uv.zIndex, zIndex)
|
||||
}
|
||||
|
||||
export {
|
||||
range,
|
||||
getPx,
|
||||
sleep,
|
||||
os,
|
||||
sys,
|
||||
random,
|
||||
guid,
|
||||
$parent,
|
||||
addStyle,
|
||||
addUnit,
|
||||
deepClone,
|
||||
deepMerge,
|
||||
error,
|
||||
randomArray,
|
||||
timeFormat,
|
||||
timeFrom,
|
||||
trim,
|
||||
queryParams,
|
||||
toast,
|
||||
type2icon,
|
||||
priceFormat,
|
||||
getDuration,
|
||||
padZero,
|
||||
formValidate,
|
||||
getProperty,
|
||||
setProperty,
|
||||
page,
|
||||
pages,
|
||||
getHistoryPage,
|
||||
setConfig
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* 注意:
|
||||
* 此部分内容,在vue-cli模式下,需要在vue.config.js加入如下内容才有效:
|
||||
* module.exports = {
|
||||
* transpileDependencies: ['uview-v2']
|
||||
* }
|
||||
*/
|
||||
|
||||
let platform = 'none'
|
||||
|
||||
// #ifdef VUE3
|
||||
platform = 'vue3'
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE2
|
||||
platform = 'vue2'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
platform = 'plus'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
platform = 'nvue'
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
platform = 'h5'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
platform = 'weixin'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
platform = 'alipay'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-BAIDU
|
||||
platform = 'baidu'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
platform = 'toutiao'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-QQ
|
||||
platform = 'qq'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-KUAISHOU
|
||||
platform = 'kuaishou'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-360
|
||||
platform = '360'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
platform = 'mp'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW
|
||||
platform = 'quickapp-webview'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW-HUAWEI
|
||||
platform = 'quickapp-webview-huawei'
|
||||
// #endif
|
||||
|
||||
// #ifdef QUICKAPP-WEBVIEW-UNION
|
||||
platform = 'quckapp-webview-union'
|
||||
// #endif
|
||||
|
||||
export default platform
|
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* 验证电子邮箱格式
|
||||
*/
|
||||
function email(value) {
|
||||
return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证手机格式
|
||||
*/
|
||||
function mobile(value) {
|
||||
return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证URL格式
|
||||
*/
|
||||
function url(value) {
|
||||
return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
|
||||
.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证日期格式
|
||||
*/
|
||||
function date(value) {
|
||||
if (!value) return false
|
||||
// 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
|
||||
if (number(value)) value = +value
|
||||
return !/Invalid|NaN/.test(new Date(value).toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证ISO类型的日期格式
|
||||
*/
|
||||
function dateISO(value) {
|
||||
return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证十进制数字
|
||||
*/
|
||||
function number(value) {
|
||||
return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证字符串
|
||||
*/
|
||||
function string(value) {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证整数
|
||||
*/
|
||||
function digits(value) {
|
||||
return /^\d+$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证身份证号码
|
||||
*/
|
||||
function idCard(value) {
|
||||
return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否车牌号
|
||||
*/
|
||||
function carNo(value) {
|
||||
// 新能源车牌
|
||||
const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
|
||||
// 旧车牌
|
||||
const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
|
||||
if (value.length === 7) {
|
||||
return creg.test(value)
|
||||
} if (value.length === 8) {
|
||||
return xreg.test(value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 金额,只允许2位小数
|
||||
*/
|
||||
function amount(value) {
|
||||
// 金额,只允许保留两位小数
|
||||
return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 中文
|
||||
*/
|
||||
function chinese(value) {
|
||||
const reg = /^[\u4e00-\u9fa5]+$/gi
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能输入字母
|
||||
*/
|
||||
function letter(value) {
|
||||
return /^[a-zA-Z]*$/.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 只能是字母或者数字
|
||||
*/
|
||||
function enOrNum(value) {
|
||||
// 英文或者数字
|
||||
const reg = /^[0-9a-zA-Z]*$/g
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证是否包含某个值
|
||||
*/
|
||||
function contains(value, param) {
|
||||
return value.indexOf(param) >= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个值范围[min, max]
|
||||
*/
|
||||
function range(value, param) {
|
||||
return value >= param[0] && value <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证一个长度范围[min, max]
|
||||
*/
|
||||
function rangeLength(value, param) {
|
||||
return value.length >= param[0] && value.length <= param[1]
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否固定电话
|
||||
*/
|
||||
function landline(value) {
|
||||
const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
|
||||
return reg.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为空
|
||||
*/
|
||||
function empty(value) {
|
||||
switch (typeof value) {
|
||||
case 'undefined':
|
||||
return true
|
||||
case 'string':
|
||||
if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
|
||||
break
|
||||
case 'boolean':
|
||||
if (!value) return true
|
||||
break
|
||||
case 'number':
|
||||
if (value === 0 || isNaN(value)) return true
|
||||
break
|
||||
case 'object':
|
||||
if (value === null || value.length === 0) return true
|
||||
for (const i in value) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否json字符串
|
||||
*/
|
||||
function jsonString(value) {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
const obj = JSON.parse(value)
|
||||
if (typeof obj === 'object' && obj) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否数组
|
||||
*/
|
||||
function array(value) {
|
||||
if (typeof Array.isArray === 'function') {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
return Object.prototype.toString.call(value) === '[object Array]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否对象
|
||||
*/
|
||||
function object(value) {
|
||||
return Object.prototype.toString.call(value) === '[object Object]'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否短信验证码
|
||||
*/
|
||||
function code(value, len = 6) {
|
||||
return new RegExp(`^\\d{${len}}$`).test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否函数方法
|
||||
* @param {Object} value
|
||||
*/
|
||||
function func(value) {
|
||||
return typeof value === 'function'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否promise对象
|
||||
* @param {Object} value
|
||||
*/
|
||||
function promise(value) {
|
||||
return object(value) && func(value.then) && func(value.catch)
|
||||
}
|
||||
|
||||
/** 是否图片格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function image(value) {
|
||||
const newValue = value.split('?')[0]
|
||||
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
|
||||
return IMAGE_REGEXP.test(newValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否视频格式
|
||||
* @param {Object} value
|
||||
*/
|
||||
function video(value) {
|
||||
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
|
||||
return VIDEO_REGEXP.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为正则对象
|
||||
* @param {Object}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function regExp(o) {
|
||||
return o && Object.prototype.toString.call(o) === '[object RegExp]'
|
||||
}
|
||||
|
||||
export {
|
||||
email,
|
||||
mobile,
|
||||
url,
|
||||
date,
|
||||
dateISO,
|
||||
number,
|
||||
digits,
|
||||
idCard,
|
||||
carNo,
|
||||
amount,
|
||||
chinese,
|
||||
letter,
|
||||
enOrNum,
|
||||
contains,
|
||||
range,
|
||||
rangeLength,
|
||||
empty,
|
||||
jsonString,
|
||||
landline,
|
||||
object,
|
||||
array,
|
||||
code,
|
||||
func,
|
||||
promise,
|
||||
video,
|
||||
image,
|
||||
regExp,
|
||||
string
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
let timer; let
|
||||
flag
|
||||
/**
|
||||
* 节流原理:在一定时间内,只能触发一次
|
||||
*
|
||||
* @param {Function} func 要执行的回调函数
|
||||
* @param {Number} wait 延时的时间
|
||||
* @param {Boolean} immediate 是否立即执行
|
||||
* @return null
|
||||
*/
|
||||
function throttle(func, wait = 500, immediate = true) {
|
||||
if (immediate) {
|
||||
if (!flag) {
|
||||
flag = true
|
||||
// 如果是立即执行,则在wait毫秒内开始时执行
|
||||
typeof func === 'function' && func()
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
}, wait)
|
||||
}
|
||||
} else if (!flag) {
|
||||
flag = true
|
||||
// 如果是非立即执行,则在wait毫秒内的结束处执行
|
||||
timer = setTimeout(() => {
|
||||
flag = false
|
||||
typeof func === 'function' && func()
|
||||
}, wait)
|
||||
}
|
||||
}
|
||||
export default throttle
|
|
@ -0,0 +1,97 @@
|
|||
import buildURL from '../helpers/buildURL'
|
||||
import buildFullPath from '../core/buildFullPath'
|
||||
import settle from '../core/settle'
|
||||
import { isUndefined } from '../utils'
|
||||
|
||||
/**
|
||||
* 返回可选值存在的配置
|
||||
* @param {Array} keys - 可选值数组
|
||||
* @param {Object} config2 - 配置
|
||||
* @return {{}} - 存在的配置项
|
||||
*/
|
||||
const mergeKeys = (keys, config2) => {
|
||||
const config = {}
|
||||
keys.forEach((prop) => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
export default (config) => new Promise((resolve, reject) => {
|
||||
const fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params)
|
||||
const _config = {
|
||||
url: fullPath,
|
||||
header: config.header,
|
||||
complete: (response) => {
|
||||
config.fullPath = fullPath
|
||||
response.config = config
|
||||
try {
|
||||
// 对可能字符串不是json 的情况容错
|
||||
if (typeof response.data === 'string') {
|
||||
response.data = JSON.parse(response.data)
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {
|
||||
}
|
||||
settle(resolve, reject, response)
|
||||
}
|
||||
}
|
||||
let requestTask
|
||||
if (config.method === 'UPLOAD') {
|
||||
delete _config.header['content-type']
|
||||
delete _config.header['Content-Type']
|
||||
const otherConfig = {
|
||||
// #ifdef MP-ALIPAY
|
||||
fileType: config.fileType,
|
||||
// #endif
|
||||
filePath: config.filePath,
|
||||
name: config.name
|
||||
}
|
||||
const optionalKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
// #ifdef H5 || APP-PLUS
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData'
|
||||
]
|
||||
requestTask = uni.uploadFile({ ..._config, ...otherConfig, ...mergeKeys(optionalKeys, config) })
|
||||
} else if (config.method === 'DOWNLOAD') {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (!isUndefined(config.timeout)) {
|
||||
_config.timeout = config.timeout
|
||||
}
|
||||
// #endif
|
||||
requestTask = uni.downloadFile(_config)
|
||||
} else {
|
||||
const optionalKeys = [
|
||||
'data',
|
||||
'method',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4'
|
||||
// #endif
|
||||
]
|
||||
requestTask = uni.request({ ..._config, ...mergeKeys(optionalKeys, config) })
|
||||
}
|
||||
if (config.getTask) {
|
||||
config.getTask(requestTask, config)
|
||||
}
|
||||
})
|
|
@ -0,0 +1,50 @@
|
|||
'use strict'
|
||||
|
||||
function InterceptorManager() {
|
||||
this.handlers = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new interceptor to the stack
|
||||
*
|
||||
* @param {Function} fulfilled The function to handle `then` for a `Promise`
|
||||
* @param {Function} rejected The function to handle `reject` for a `Promise`
|
||||
*
|
||||
* @return {Number} An ID used to remove interceptor later
|
||||
*/
|
||||
InterceptorManager.prototype.use = function use(fulfilled, rejected) {
|
||||
this.handlers.push({
|
||||
fulfilled,
|
||||
rejected
|
||||
})
|
||||
return this.handlers.length - 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an interceptor from the stack
|
||||
*
|
||||
* @param {Number} id The ID that was returned by `use`
|
||||
*/
|
||||
InterceptorManager.prototype.eject = function eject(id) {
|
||||
if (this.handlers[id]) {
|
||||
this.handlers[id] = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all the registered interceptors
|
||||
*
|
||||
* This method is particularly useful for skipping over any
|
||||
* interceptors that may have become `null` calling `eject`.
|
||||
*
|
||||
* @param {Function} fn The function to call for each interceptor
|
||||
*/
|
||||
InterceptorManager.prototype.forEach = function forEach(fn) {
|
||||
this.handlers.forEach((h) => {
|
||||
if (h !== null) {
|
||||
fn(h)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default InterceptorManager
|
|
@ -0,0 +1,198 @@
|
|||
/**
|
||||
* @Class Request
|
||||
* @description luch-request http请求插件
|
||||
* @version 3.0.7
|
||||
* @Author lu-ch
|
||||
* @Date 2021-09-04
|
||||
* @Email webwork.s@qq.com
|
||||
* 文档: https://www.quanzhan.co/luch-request/
|
||||
* github: https://github.com/lei-mu/luch-request
|
||||
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
|
||||
* HBuilderX: beat-3.0.4 alpha-3.0.4
|
||||
*/
|
||||
|
||||
import dispatchRequest from './dispatchRequest'
|
||||
import InterceptorManager from './InterceptorManager'
|
||||
import mergeConfig from './mergeConfig'
|
||||
import defaults from './defaults'
|
||||
import { isPlainObject } from '../utils'
|
||||
import clone from '../utils/clone'
|
||||
|
||||
export default class Request {
|
||||
/**
|
||||
* @param {Object} arg - 全局配置
|
||||
* @param {String} arg.baseURL - 全局根路径
|
||||
* @param {Object} arg.header - 全局header
|
||||
* @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
|
||||
* @param {String} arg.dataType = [json] - 全局默认的dataType
|
||||
* @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
|
||||
* @param {Object} arg.custom - 全局默认的自定义参数
|
||||
* @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
|
||||
* @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
|
||||
* @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
|
||||
* @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
|
||||
* @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
|
||||
*/
|
||||
constructor(arg = {}) {
|
||||
if (!isPlainObject(arg)) {
|
||||
arg = {}
|
||||
console.warn('设置全局参数必须接收一个Object')
|
||||
}
|
||||
this.config = clone({ ...defaults, ...arg })
|
||||
this.interceptors = {
|
||||
request: new InterceptorManager(),
|
||||
response: new InterceptorManager()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Request~setConfigCallback} f - 设置全局默认配置
|
||||
*/
|
||||
setConfig(f) {
|
||||
this.config = f(this.config)
|
||||
}
|
||||
|
||||
middleware(config) {
|
||||
config = mergeConfig(this.config, config)
|
||||
const chain = [dispatchRequest, undefined]
|
||||
let promise = Promise.resolve(config)
|
||||
|
||||
this.interceptors.request.forEach((interceptor) => {
|
||||
chain.unshift(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
this.interceptors.response.forEach((interceptor) => {
|
||||
chain.push(interceptor.fulfilled, interceptor.rejected)
|
||||
})
|
||||
|
||||
while (chain.length) {
|
||||
promise = promise.then(chain.shift(), chain.shift())
|
||||
}
|
||||
|
||||
return promise
|
||||
}
|
||||
|
||||
/**
|
||||
* @Function
|
||||
* @param {Object} config - 请求配置项
|
||||
* @prop {String} options.url - 请求路径
|
||||
* @prop {Object} options.data - 请求参数
|
||||
* @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
|
||||
* @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
|
||||
* @prop {Object} [options.header = config.header] - 请求header
|
||||
* @prop {Object} [options.method = config.method] - 请求方法
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
request(config = {}) {
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
get(url, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
method: 'GET',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
post(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'POST',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #ifndef MP-ALIPAY
|
||||
put(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'PUT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
delete(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'DELETE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
connect(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'CONNECT',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN || MP-BAIDU
|
||||
head(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'HEAD',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
|
||||
options(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'OPTIONS',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
// #ifdef H5 || MP-WEIXIN
|
||||
trace(url, data, options = {}) {
|
||||
return this.middleware({
|
||||
url,
|
||||
data,
|
||||
method: 'TRACE',
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
upload(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'UPLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
|
||||
download(url, config = {}) {
|
||||
config.url = url
|
||||
config.method = 'DOWNLOAD'
|
||||
return this.middleware(config)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* setConfig回调
|
||||
* @return {Object} - 返回操作后的config
|
||||
* @callback Request~setConfigCallback
|
||||
* @param {Object} config - 全局默认config
|
||||
*/
|
|
@ -0,0 +1,20 @@
|
|||
'use strict'
|
||||
|
||||
import isAbsoluteURL from '../helpers/isAbsoluteURL'
|
||||
import combineURLs from '../helpers/combineURLs'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the baseURL with the requestedURL,
|
||||
* only when the requestedURL is not already an absolute URL.
|
||||
* If the requestURL is absolute, this function returns the requestedURL untouched.
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} requestedURL Absolute or relative URL to combine
|
||||
* @returns {string} The combined full path
|
||||
*/
|
||||
export default function buildFullPath(baseURL, requestedURL) {
|
||||
if (baseURL && !isAbsoluteURL(requestedURL)) {
|
||||
return combineURLs(baseURL, requestedURL)
|
||||
}
|
||||
return requestedURL
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 默认的全局配置
|
||||
*/
|
||||
|
||||
export default {
|
||||
baseURL: '',
|
||||
header: {},
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
// #ifndef MP-ALIPAY
|
||||
responseType: 'text',
|
||||
// #endif
|
||||
custom: {},
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
timeout: 60000,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
sslVerify: true,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
withCredentials: false,
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
firstIpv4: false,
|
||||
// #endif
|
||||
validateStatus: function validateStatus(status) {
|
||||
return status >= 200 && status < 300
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import adapter from '../adapters/index'
|
||||
|
||||
export default (config) => adapter(config)
|
|
@ -0,0 +1,103 @@
|
|||
import { deepMerge, isUndefined } from '../utils'
|
||||
|
||||
/**
|
||||
* 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
|
||||
* @param {Array} keys - 配置项
|
||||
* @param {Object} globalsConfig - 当前的全局配置
|
||||
* @param {Object} config2 - 局部配置
|
||||
* @return {{}}
|
||||
*/
|
||||
const mergeKeys = (keys, globalsConfig, config2) => {
|
||||
const config = {}
|
||||
keys.forEach((prop) => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
} else if (!isUndefined(globalsConfig[prop])) {
|
||||
config[prop] = globalsConfig[prop]
|
||||
}
|
||||
})
|
||||
return config
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param globalsConfig - 当前实例的全局配置
|
||||
* @param config2 - 当前的局部配置
|
||||
* @return - 合并后的配置
|
||||
*/
|
||||
export default (globalsConfig, config2 = {}) => {
|
||||
const method = config2.method || globalsConfig.method || 'GET'
|
||||
let config = {
|
||||
baseURL: globalsConfig.baseURL || '',
|
||||
method,
|
||||
url: config2.url || '',
|
||||
params: config2.params || {},
|
||||
custom: { ...(globalsConfig.custom || {}), ...(config2.custom || {}) },
|
||||
header: deepMerge(globalsConfig.header || {}, config2.header || {})
|
||||
}
|
||||
const defaultToConfig2Keys = ['getTask', 'validateStatus']
|
||||
config = { ...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2) }
|
||||
|
||||
// eslint-disable-next-line no-empty
|
||||
if (method === 'DOWNLOAD') {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (!isUndefined(config2.timeout)) {
|
||||
config.timeout = config2.timeout
|
||||
} else if (!isUndefined(globalsConfig.timeout)) {
|
||||
config.timeout = globalsConfig.timeout
|
||||
}
|
||||
// #endif
|
||||
} else if (method === 'UPLOAD') {
|
||||
delete config.header['content-type']
|
||||
delete config.header['Content-Type']
|
||||
const uploadKeys = [
|
||||
// #ifdef APP-PLUS || H5
|
||||
'files',
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
'fileType',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'file',
|
||||
// #endif
|
||||
'filePath',
|
||||
'name',
|
||||
// #ifdef H5 || APP-PLUS
|
||||
'timeout',
|
||||
// #endif
|
||||
'formData'
|
||||
]
|
||||
uploadKeys.forEach((prop) => {
|
||||
if (!isUndefined(config2[prop])) {
|
||||
config[prop] = config2[prop]
|
||||
}
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
|
||||
config.timeout = globalsConfig.timeout
|
||||
}
|
||||
// #endif
|
||||
} else {
|
||||
const defaultsKeys = [
|
||||
'data',
|
||||
// #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
|
||||
'timeout',
|
||||
// #endif
|
||||
'dataType',
|
||||
// #ifndef MP-ALIPAY
|
||||
'responseType',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'sslVerify',
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
'withCredentials',
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
'firstIpv4'
|
||||
// #endif
|
||||
]
|
||||
config = { ...config, ...mergeKeys(defaultsKeys, globalsConfig, config2) }
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Resolve or reject a Promise based on response status.
|
||||
*
|
||||
* @param {Function} resolve A function that resolves the promise.
|
||||
* @param {Function} reject A function that rejects the promise.
|
||||
* @param {object} response The response.
|
||||
*/
|
||||
export default function settle(resolve, reject, response) {
|
||||
const { validateStatus } = response.config
|
||||
const status = response.statusCode
|
||||
if (status && (!validateStatus || validateStatus(status))) {
|
||||
resolve(response)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
'use strict'
|
||||
|
||||
import * as utils from '../utils'
|
||||
|
||||
function encode(val) {
|
||||
return encodeURIComponent(val)
|
||||
.replace(/%40/gi, '@')
|
||||
.replace(/%3A/gi, ':')
|
||||
.replace(/%24/g, '$')
|
||||
.replace(/%2C/gi, ',')
|
||||
.replace(/%20/g, '+')
|
||||
.replace(/%5B/gi, '[')
|
||||
.replace(/%5D/gi, ']')
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a URL by appending params to the end
|
||||
*
|
||||
* @param {string} url The base of the url (e.g., http://www.google.com)
|
||||
* @param {object} [params] The params to be appended
|
||||
* @returns {string} The formatted url
|
||||
*/
|
||||
export default function buildURL(url, params) {
|
||||
/* eslint no-param-reassign:0 */
|
||||
if (!params) {
|
||||
return url
|
||||
}
|
||||
|
||||
let serializedParams
|
||||
if (utils.isURLSearchParams(params)) {
|
||||
serializedParams = params.toString()
|
||||
} else {
|
||||
const parts = []
|
||||
|
||||
utils.forEach(params, (val, key) => {
|
||||
if (val === null || typeof val === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
if (utils.isArray(val)) {
|
||||
key = `${key}[]`
|
||||
} else {
|
||||
val = [val]
|
||||
}
|
||||
|
||||
utils.forEach(val, (v) => {
|
||||
if (utils.isDate(v)) {
|
||||
v = v.toISOString()
|
||||
} else if (utils.isObject(v)) {
|
||||
v = JSON.stringify(v)
|
||||
}
|
||||
parts.push(`${encode(key)}=${encode(v)}`)
|
||||
})
|
||||
})
|
||||
|
||||
serializedParams = parts.join('&')
|
||||
}
|
||||
|
||||
if (serializedParams) {
|
||||
const hashmarkIndex = url.indexOf('#')
|
||||
if (hashmarkIndex !== -1) {
|
||||
url = url.slice(0, hashmarkIndex)
|
||||
}
|
||||
|
||||
url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
'use strict'
|
||||
|
||||
/**
|
||||
* Creates a new URL by combining the specified URLs
|
||||
*
|
||||
* @param {string} baseURL The base URL
|
||||
* @param {string} relativeURL The relative URL
|
||||
* @returns {string} The combined URL
|
||||
*/
|
||||
export default function combineURLs(baseURL, relativeURL) {
|
||||
return relativeURL
|
||||
? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}`
|
||||
: baseURL
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
'use strict'
|
||||
|
||||
/**
|
||||
* Determines whether the specified URL is absolute
|
||||
*
|
||||
* @param {string} url The URL to test
|
||||
* @returns {boolean} True if the specified URL is absolute, otherwise false
|
||||
*/
|
||||
export default function isAbsoluteURL(url) {
|
||||
// A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
|
||||
// RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
|
||||
// by any combination of letters, digits, plus, period, or hyphen.
|
||||
return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
type AnyObject = Record<string | number | symbol, any>
|
||||
type HttpPromise<T> = Promise<HttpResponse<T>>;
|
||||
type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask
|
||||
export interface RequestTask {
|
||||
abort: () => void;
|
||||
offHeadersReceived: () => void;
|
||||
onHeadersReceived: () => void;
|
||||
}
|
||||
export interface HttpRequestConfig<T = Tasks> {
|
||||
/** 请求基地址 */
|
||||
baseURL?: string;
|
||||
/** 请求服务器接口地址 */
|
||||
url?: string;
|
||||
|
||||
/** 请求查询参数,自动拼接为查询字符串 */
|
||||
params?: AnyObject;
|
||||
/** 请求体参数 */
|
||||
data?: AnyObject;
|
||||
|
||||
/** 文件对应的 key */
|
||||
name?: string;
|
||||
/** HTTP 请求中其他额外的 form data */
|
||||
formData?: AnyObject;
|
||||
/** 要上传文件资源的路径。 */
|
||||
filePath?: string;
|
||||
/** 需要上传的文件列表。使用 files 时,filePath 和 name 不生效,App、H5( 2.6.15+) */
|
||||
files?: Array<{
|
||||
name?: string;
|
||||
file?: File;
|
||||
uri: string;
|
||||
}>;
|
||||
/** 要上传的文件对象,仅H5(2.6.15+)支持 */
|
||||
file?: File;
|
||||
|
||||
/** 请求头信息 */
|
||||
header?: AnyObject;
|
||||
/** 请求方式 */
|
||||
method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD";
|
||||
/** 如果设为 json,会尝试对返回的数据做一次 JSON.parse */
|
||||
dataType?: string;
|
||||
/** 设置响应的数据类型,支付宝小程序不支持 */
|
||||
responseType?: "text" | "arraybuffer";
|
||||
/** 自定义参数 */
|
||||
custom?: AnyObject;
|
||||
/** 超时时间,仅微信小程序(2.10.0)、支付宝小程序支持 */
|
||||
timeout?: number;
|
||||
/** DNS解析时优先使用ipv4,仅 App-Android 支持 (HBuilderX 2.8.0+) */
|
||||
firstIpv4?: boolean;
|
||||
/** 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) */
|
||||
sslVerify?: boolean;
|
||||
/** 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) */
|
||||
withCredentials?: boolean;
|
||||
|
||||
/** 返回当前请求的task, options。请勿在此处修改options。 */
|
||||
getTask?: (task: T, options: HttpRequestConfig<T>) => void;
|
||||
/** 全局自定义验证器 */
|
||||
validateStatus?: (statusCode: number) => boolean | void;
|
||||
}
|
||||
export interface HttpResponse<T = any> {
|
||||
config: HttpRequestConfig;
|
||||
statusCode: number;
|
||||
cookies: Array<string>;
|
||||
data: T;
|
||||
errMsg: string;
|
||||
header: AnyObject;
|
||||
}
|
||||
export interface HttpUploadResponse<T = any> {
|
||||
config: HttpRequestConfig;
|
||||
statusCode: number;
|
||||
data: T;
|
||||
errMsg: string;
|
||||
}
|
||||
export interface HttpDownloadResponse extends HttpResponse {
|
||||
tempFilePath: string;
|
||||
}
|
||||
export interface HttpError {
|
||||
config: HttpRequestConfig;
|
||||
statusCode?: number;
|
||||
cookies?: Array<string>;
|
||||
data?: any;
|
||||
errMsg: string;
|
||||
header?: AnyObject;
|
||||
}
|
||||
export interface HttpInterceptorManager<V, E = V> {
|
||||
use(
|
||||
onFulfilled?: (config: V) => Promise<V> | V,
|
||||
onRejected?: (config: E) => Promise<E> | E
|
||||
): void;
|
||||
eject(id: number): void;
|
||||
}
|
||||
export abstract class HttpRequestAbstract {
|
||||
constructor(config?: HttpRequestConfig);
|
||||
config: HttpRequestConfig;
|
||||
interceptors: {
|
||||
request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>;
|
||||
response: HttpInterceptorManager<HttpResponse, HttpError>;
|
||||
}
|
||||
middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>;
|
||||
request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>;
|
||||
delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
|
||||
|
||||
download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>;
|
||||
|
||||
setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
|
||||
}
|
||||
|
||||
declare class HttpRequest extends HttpRequestAbstract { }
|
||||
export default HttpRequest;
|
|
@ -0,0 +1,3 @@
|
|||
import Request from './core/Request'
|
||||
|
||||
export default Request
|
|
@ -0,0 +1,131 @@
|
|||
'use strict'
|
||||
|
||||
// utils is a library of generic helper functions non-specific to axios
|
||||
|
||||
const { toString } = Object.prototype
|
||||
|
||||
/**
|
||||
* Determine if a value is an Array
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Array, otherwise false
|
||||
*/
|
||||
export function isArray(val) {
|
||||
return toString.call(val) === '[object Array]'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is an Object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is an Object, otherwise false
|
||||
*/
|
||||
export function isObject(val) {
|
||||
return val !== null && typeof val === 'object'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a Date
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a Date, otherwise false
|
||||
*/
|
||||
export function isDate(val) {
|
||||
return toString.call(val) === '[object Date]'
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a value is a URLSearchParams object
|
||||
*
|
||||
* @param {Object} val The value to test
|
||||
* @returns {boolean} True if value is a URLSearchParams object, otherwise false
|
||||
*/
|
||||
export function isURLSearchParams(val) {
|
||||
return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over an Array or an Object invoking a function for each item.
|
||||
*
|
||||
* If `obj` is an Array callback will be called passing
|
||||
* the value, index, and complete array for each item.
|
||||
*
|
||||
* If 'obj' is an Object callback will be called passing
|
||||
* the value, key, and complete object for each property.
|
||||
*
|
||||
* @param {Object|Array} obj The object to iterate
|
||||
* @param {Function} fn The callback to invoke for each item
|
||||
*/
|
||||
export function forEach(obj, fn) {
|
||||
// Don't bother if no value provided
|
||||
if (obj === null || typeof obj === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
// Force an array if not already something iterable
|
||||
if (typeof obj !== 'object') {
|
||||
/* eslint no-param-reassign:0 */
|
||||
obj = [obj]
|
||||
}
|
||||
|
||||
if (isArray(obj)) {
|
||||
// Iterate over array values
|
||||
for (let i = 0, l = obj.length; i < l; i++) {
|
||||
fn.call(null, obj[i], i, obj)
|
||||
}
|
||||
} else {
|
||||
// Iterate over object keys
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
fn.call(null, obj[key], key, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为boolean 值
|
||||
* @param val
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isBoolean(val) {
|
||||
return typeof val === 'boolean'
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为真正的对象{} new Object
|
||||
* @param {any} obj - 检测的对象
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPlainObject(obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Object]'
|
||||
}
|
||||
|
||||
/**
|
||||
* Function equal to merge with the difference being that no reference
|
||||
* to original objects is kept.
|
||||
*
|
||||
* @see merge
|
||||
* @param {Object} obj1 Object to merge
|
||||
* @returns {Object} Result of all merge properties
|
||||
*/
|
||||
export function deepMerge(/* obj1, obj2, obj3, ... */) {
|
||||
const result = {}
|
||||
function assignValue(val, key) {
|
||||
if (typeof result[key] === 'object' && typeof val === 'object') {
|
||||
result[key] = deepMerge(result[key], val)
|
||||
} else if (typeof val === 'object') {
|
||||
result[key] = deepMerge({}, val)
|
||||
} else {
|
||||
result[key] = val
|
||||
}
|
||||
}
|
||||
for (let i = 0, l = arguments.length; i < l; i++) {
|
||||
forEach(arguments[i], assignValue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export function isUndefined(val) {
|
||||
return typeof val === 'undefined'
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
/* eslint-disable */
|
||||
var clone = (function() {
|
||||
'use strict';
|
||||
|
||||
function _instanceof(obj, type) {
|
||||
return type != null && obj instanceof type;
|
||||
}
|
||||
|
||||
var nativeMap;
|
||||
try {
|
||||
nativeMap = Map;
|
||||
} catch(_) {
|
||||
// maybe a reference error because no `Map`. Give it a dummy value that no
|
||||
// value will ever be an instanceof.
|
||||
nativeMap = function() {};
|
||||
}
|
||||
|
||||
var nativeSet;
|
||||
try {
|
||||
nativeSet = Set;
|
||||
} catch(_) {
|
||||
nativeSet = function() {};
|
||||
}
|
||||
|
||||
var nativePromise;
|
||||
try {
|
||||
nativePromise = Promise;
|
||||
} catch(_) {
|
||||
nativePromise = function() {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones (copies) an Object using deep copying.
|
||||
*
|
||||
* This function supports circular references by default, but if you are certain
|
||||
* there are no circular references in your object, you can save some CPU time
|
||||
* by calling clone(obj, false).
|
||||
*
|
||||
* Caution: if `circular` is false and `parent` contains circular references,
|
||||
* your program may enter an infinite loop and crash.
|
||||
*
|
||||
* @param `parent` - the object to be cloned
|
||||
* @param `circular` - set to true if the object to be cloned may contain
|
||||
* circular references. (optional - true by default)
|
||||
* @param `depth` - set to a number if the object is only to be cloned to
|
||||
* a particular depth. (optional - defaults to Infinity)
|
||||
* @param `prototype` - sets the prototype to be used when cloning an object.
|
||||
* (optional - defaults to parent prototype).
|
||||
* @param `includeNonEnumerable` - set to true if the non-enumerable properties
|
||||
* should be cloned as well. Non-enumerable properties on the prototype
|
||||
* chain will be ignored. (optional - false by default)
|
||||
*/
|
||||
function clone(parent, circular, depth, prototype, includeNonEnumerable) {
|
||||
if (typeof circular === 'object') {
|
||||
depth = circular.depth;
|
||||
prototype = circular.prototype;
|
||||
includeNonEnumerable = circular.includeNonEnumerable;
|
||||
circular = circular.circular;
|
||||
}
|
||||
// maintain two arrays for circular references, where corresponding parents
|
||||
// and children have the same index
|
||||
var allParents = [];
|
||||
var allChildren = [];
|
||||
|
||||
var useBuffer = typeof Buffer != 'undefined';
|
||||
|
||||
if (typeof circular == 'undefined')
|
||||
circular = true;
|
||||
|
||||
if (typeof depth == 'undefined')
|
||||
depth = Infinity;
|
||||
|
||||
// recurse this function so we don't reset allParents and allChildren
|
||||
function _clone(parent, depth) {
|
||||
// cloning null always returns null
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
if (depth === 0)
|
||||
return parent;
|
||||
|
||||
var child;
|
||||
var proto;
|
||||
if (typeof parent != 'object') {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
child = new nativeMap();
|
||||
} else if (_instanceof(parent, nativeSet)) {
|
||||
child = new nativeSet();
|
||||
} else if (_instanceof(parent, nativePromise)) {
|
||||
child = new nativePromise(function (resolve, reject) {
|
||||
parent.then(function(value) {
|
||||
resolve(_clone(value, depth - 1));
|
||||
}, function(err) {
|
||||
reject(_clone(err, depth - 1));
|
||||
});
|
||||
});
|
||||
} else if (clone.__isArray(parent)) {
|
||||
child = [];
|
||||
} else if (clone.__isRegExp(parent)) {
|
||||
child = new RegExp(parent.source, __getRegExpFlags(parent));
|
||||
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
|
||||
} else if (clone.__isDate(parent)) {
|
||||
child = new Date(parent.getTime());
|
||||
} else if (useBuffer && Buffer.isBuffer(parent)) {
|
||||
if (Buffer.from) {
|
||||
// Node.js >= 5.10.0
|
||||
child = Buffer.from(parent);
|
||||
} else {
|
||||
// Older Node.js versions
|
||||
child = new Buffer(parent.length);
|
||||
parent.copy(child);
|
||||
}
|
||||
return child;
|
||||
} else if (_instanceof(parent, Error)) {
|
||||
child = Object.create(parent);
|
||||
} else {
|
||||
if (typeof prototype == 'undefined') {
|
||||
proto = Object.getPrototypeOf(parent);
|
||||
child = Object.create(proto);
|
||||
}
|
||||
else {
|
||||
child = Object.create(prototype);
|
||||
proto = prototype;
|
||||
}
|
||||
}
|
||||
|
||||
if (circular) {
|
||||
var index = allParents.indexOf(parent);
|
||||
|
||||
if (index != -1) {
|
||||
return allChildren[index];
|
||||
}
|
||||
allParents.push(parent);
|
||||
allChildren.push(child);
|
||||
}
|
||||
|
||||
if (_instanceof(parent, nativeMap)) {
|
||||
parent.forEach(function(value, key) {
|
||||
var keyChild = _clone(key, depth - 1);
|
||||
var valueChild = _clone(value, depth - 1);
|
||||
child.set(keyChild, valueChild);
|
||||
});
|
||||
}
|
||||
if (_instanceof(parent, nativeSet)) {
|
||||
parent.forEach(function(value) {
|
||||
var entryChild = _clone(value, depth - 1);
|
||||
child.add(entryChild);
|
||||
});
|
||||
}
|
||||
|
||||
for (var i in parent) {
|
||||
var attrs = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (attrs) {
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
}
|
||||
|
||||
try {
|
||||
var objProperty = Object.getOwnPropertyDescriptor(parent, i);
|
||||
if (objProperty.set === 'undefined') {
|
||||
// no setter defined. Skip cloning this property
|
||||
continue;
|
||||
}
|
||||
child[i] = _clone(parent[i], depth - 1);
|
||||
} catch(e){
|
||||
if (e instanceof TypeError) {
|
||||
// when in strict mode, TypeError will be thrown if child[i] property only has a getter
|
||||
// we can't do anything about this, other than inform the user that this property cannot be set.
|
||||
continue
|
||||
} else if (e instanceof ReferenceError) {
|
||||
//this may happen in non strict mode
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
var symbols = Object.getOwnPropertySymbols(parent);
|
||||
for (var i = 0; i < symbols.length; i++) {
|
||||
// Don't need to worry about cloning a symbol because it is a primitive,
|
||||
// like a number or string.
|
||||
var symbol = symbols[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
|
||||
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
|
||||
continue;
|
||||
}
|
||||
child[symbol] = _clone(parent[symbol], depth - 1);
|
||||
Object.defineProperty(child, symbol, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeNonEnumerable) {
|
||||
var allPropertyNames = Object.getOwnPropertyNames(parent);
|
||||
for (var i = 0; i < allPropertyNames.length; i++) {
|
||||
var propertyName = allPropertyNames[i];
|
||||
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
|
||||
if (descriptor && descriptor.enumerable) {
|
||||
continue;
|
||||
}
|
||||
child[propertyName] = _clone(parent[propertyName], depth - 1);
|
||||
Object.defineProperty(child, propertyName, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
return _clone(parent, depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple flat clone using prototype, accepts only objects, usefull for property
|
||||
* override on FLAT configuration object (no nested props).
|
||||
*
|
||||
* USE WITH CAUTION! This may not behave as you wish if you do not know how this
|
||||
* works.
|
||||
*/
|
||||
clone.clonePrototype = function clonePrototype(parent) {
|
||||
if (parent === null)
|
||||
return null;
|
||||
|
||||
var c = function () {};
|
||||
c.prototype = parent;
|
||||
return new c();
|
||||
};
|
||||
|
||||
// private utility functions
|
||||
|
||||
function __objToStr(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
clone.__objToStr = __objToStr;
|
||||
|
||||
function __isDate(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Date]';
|
||||
}
|
||||
clone.__isDate = __isDate;
|
||||
|
||||
function __isArray(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object Array]';
|
||||
}
|
||||
clone.__isArray = __isArray;
|
||||
|
||||
function __isRegExp(o) {
|
||||
return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
|
||||
}
|
||||
clone.__isRegExp = __isRegExp;
|
||||
|
||||
function __getRegExpFlags(re) {
|
||||
var flags = '';
|
||||
if (re.global) flags += 'g';
|
||||
if (re.ignoreCase) flags += 'i';
|
||||
if (re.multiline) flags += 'm';
|
||||
return flags;
|
||||
}
|
||||
clone.__getRegExpFlags = __getRegExpFlags;
|
||||
|
||||
return clone;
|
||||
})();
|
||||
|
||||
export default clone
|
|
@ -0,0 +1,13 @@
|
|||
export default {
|
||||
props: {
|
||||
lang: String,
|
||||
sessionFrom: String,
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: Boolean,
|
||||
appParameter: String,
|
||||
formType: String,
|
||||
openType: String
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
import * as index from '../function/index.js';
|
||||
import * as test from '../function/test.js';
|
||||
export default {
|
||||
// 定义每个组件都可能需要用到的外部样式以及类名
|
||||
props: {
|
||||
// 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
|
||||
customStyle: {
|
||||
type: [Object, String],
|
||||
default: () => ({})
|
||||
},
|
||||
customClass: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 跳转的页面路径
|
||||
url: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 页面跳转的类型
|
||||
linkType: {
|
||||
type: String,
|
||||
default: 'navigateTo'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
onLoad() {
|
||||
// getRect挂载到$uv上,因为这方法需要使用in(this),所以无法把它独立成一个单独的文件导出
|
||||
this.$uv.getRect = this.$uvGetRect
|
||||
},
|
||||
created() {
|
||||
// 组件当中,只有created声明周期,为了能在组件使用,故也在created中将方法挂载到$uv
|
||||
this.$uv.getRect = this.$uvGetRect
|
||||
},
|
||||
computed: {
|
||||
$uv() {
|
||||
return {
|
||||
...index,
|
||||
test,
|
||||
unit: uni?.$uv?.config?.unit
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 生成bem规则类名
|
||||
* 由于微信小程序,H5,nvue之间绑定class的差异,无法通过:class="[bem()]"的形式进行同用
|
||||
* 故采用如下折中做法,最后返回的是数组(一般平台)或字符串(支付宝和字节跳动平台),类似['a', 'b', 'c']或'a b c'的形式
|
||||
* @param {String} name 组件名称
|
||||
* @param {Array} fixed 一直会存在的类名
|
||||
* @param {Array} change 会根据变量值为true或者false而出现或者隐藏的类名
|
||||
* @returns {Array|string}
|
||||
*/
|
||||
bem() {
|
||||
return function(name, fixed, change) {
|
||||
// 类名前缀
|
||||
const prefix = `uv-${name}--`
|
||||
const classes = {}
|
||||
if (fixed) {
|
||||
fixed.map((item) => {
|
||||
// 这里的类名,会一直存在
|
||||
classes[prefix + this[item]] = true
|
||||
})
|
||||
}
|
||||
if (change) {
|
||||
change.map((item) => {
|
||||
// 这里的类名,会根据this[item]的值为true或者false,而进行添加或者移除某一个类
|
||||
this[item] ? (classes[prefix + item] = this[item]) : (delete classes[prefix + item])
|
||||
})
|
||||
}
|
||||
return Object.keys(classes)
|
||||
// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
|
||||
// #ifdef MP-ALIPAY || MP-TOUTIAO || MP-LARK || MP-BAIDU
|
||||
.join(' ')
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 跳转某一个页面
|
||||
openPage(urlKey = 'url') {
|
||||
const url = this[urlKey]
|
||||
if (url) {
|
||||
// 执行类似uni.navigateTo的方法
|
||||
uni[this.linkType]({
|
||||
url
|
||||
})
|
||||
}
|
||||
},
|
||||
// 查询节点信息
|
||||
// 目前此方法在支付宝小程序中无法获取组件跟接点的尺寸,为支付宝的bug(2020-07-21)
|
||||
// 解决办法为在组件根部再套一个没有任何作用的view元素
|
||||
$uvGetRect(selector, all) {
|
||||
return new Promise((resolve) => {
|
||||
uni.createSelectorQuery()
|
||||
.in(this)[all ? 'selectAll' : 'select'](selector)
|
||||
.boundingClientRect((rect) => {
|
||||
if (all && Array.isArray(rect) && rect.length) {
|
||||
resolve(rect)
|
||||
}
|
||||
if (!all && rect) {
|
||||
resolve(rect)
|
||||
}
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
},
|
||||
getParentData(parentName = '') {
|
||||
// 避免在created中去定义parent变量
|
||||
if (!this.parent) this.parent = {}
|
||||
// 这里的本质原理是,通过获取父组件实例(也即类似uv-radio的父组件uv-radio-group的this)
|
||||
// 将父组件this中对应的参数,赋值给本组件(uv-radio的this)的parentData对象中对应的属性
|
||||
// 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
|
||||
// 此处并不会自动更新子组件的数据,而是依赖父组件uv-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
|
||||
this.parent = this.$uv.$parent.call(this, parentName)
|
||||
if (this.parent.children) {
|
||||
// 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
|
||||
this.parent.children.indexOf(this) === -1 && this.parent.children.push(this)
|
||||
}
|
||||
if (this.parent && this.parentData) {
|
||||
// 历遍parentData中的属性,将parent中的同名属性赋值给parentData
|
||||
Object.keys(this.parentData).map((key) => {
|
||||
this.parentData[key] = this.parent[key]
|
||||
})
|
||||
}
|
||||
},
|
||||
// 阻止事件冒泡
|
||||
preventEvent(e) {
|
||||
e && typeof(e.stopPropagation) === 'function' && e.stopPropagation()
|
||||
},
|
||||
// 空操作
|
||||
noop(e) {
|
||||
this.preventEvent(e)
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
uni.$emit('uvOnReachBottom')
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 判断当前页面是否存在parent和chldren,一般在checkbox和checkbox-group父子联动的场景会有此情况
|
||||
// 组件销毁时,移除子组件在父组件children数组中的实例,释放资源,避免数据混乱
|
||||
if (this.parent && test.array(this.parent.children)) {
|
||||
// 组件销毁时,移除父组件中的children数组中对应的实例
|
||||
const childrenList = this.parent.children
|
||||
childrenList.map((child, index) => {
|
||||
// 如果相等,则移除
|
||||
if (child === this) {
|
||||
childrenList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// 兼容vue3
|
||||
unmounted() {
|
||||
if (this.parent && test.array(this.parent.children)) {
|
||||
// 组件销毁时,移除父组件中的children数组中对应的实例
|
||||
const childrenList = this.parent.children
|
||||
childrenList.map((child, index) => {
|
||||
// 如果相等,则移除
|
||||
if (child === this) {
|
||||
childrenList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 将自定义节点设置成虚拟的(去掉自定义组件包裹层),更加接近Vue组件的表现,能更好的使用flex属性
|
||||
options: {
|
||||
virtualHost: true
|
||||
}
|
||||
// #endif
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue