Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
biz-trina5-app
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
贺双
biz-trina5-app
Commits
dcd21c31
Commit
dcd21c31
authored
May 21, 2025
by
贺世双
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
新增异常上报
parent
c02bee8e
Changes
35
Hide whitespace changes
Inline
Side-by-side
Showing
35 changed files
with
5724 additions
and
509 deletions
+5724
-509
apiList.js
api/apiList.js
+21
-0
bs-todoRemark.vue
components/baseComponents/bs-todoRemark/bs-todoRemark.vue
+64
-0
pages.json
pages.json
+4
-3
index.vue
pages/index/index.vue
+17
-1
abnormalEvent.vue
subpkg/abnormalEvent/abnormalEvent.vue
+658
-0
abnormalEventDetail.vue
subpkg/abnormalEventDetail/abnormalEventDetail.vue
+646
-0
signFor.vue
subpkg/signFor/signFor.vue
+0
-505
changelog.md
uni_modules/uni-table/changelog.md
+23
-0
uni-table.vue
uni_modules/uni-table/components/uni-table/uni-table.vue
+455
-0
uni-tbody.vue
uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
+29
-0
uni-td.vue
uni_modules/uni-table/components/uni-td/uni-td.vue
+90
-0
filter-dropdown.vue
uni_modules/uni-table/components/uni-th/filter-dropdown.vue
+503
-0
uni-th.vue
uni_modules/uni-table/components/uni-th/uni-th.vue
+278
-0
uni-thead.vue
uni_modules/uni-table/components/uni-thead/uni-thead.vue
+129
-0
table-checkbox.vue
uni_modules/uni-table/components/uni-tr/table-checkbox.vue
+179
-0
uni-tr.vue
uni_modules/uni-table/components/uni-tr/uni-tr.vue
+171
-0
en.json
uni_modules/uni-table/i18n/en.json
+9
-0
es.json
uni_modules/uni-table/i18n/es.json
+9
-0
fr.json
uni_modules/uni-table/i18n/fr.json
+9
-0
index.js
uni_modules/uni-table/i18n/index.js
+12
-0
zh-Hans.json
uni_modules/uni-table/i18n/zh-Hans.json
+9
-0
zh-Hant.json
uni_modules/uni-table/i18n/zh-Hant.json
+9
-0
package.json
uni_modules/uni-table/package.json
+86
-0
readme.md
uni_modules/uni-table/readme.md
+13
-0
changelog.md
uni_modules/zb-table/changelog.md
+106
-0
table-checkbox.vue
...b-table/components/zb-table/components/table-checkbox.vue
+180
-0
table-h5-summary.vue
...table/components/zb-table/components/table-h5-summary.vue
+78
-0
table-side-summary.vue
...ble/components/zb-table/components/table-side-summary.vue
+59
-0
table-summary.vue
...zb-table/components/zb-table/components/table-summary.vue
+77
-0
zb-load-more.vue
.../zb-table/components/zb-table/components/zb-load-more.vue
+50
-0
summary.js
uni_modules/zb-table/components/zb-table/js/summary.js
+88
-0
util.js
uni_modules/zb-table/components/zb-table/js/util.js
+51
-0
zb-table.vue
uni_modules/zb-table/components/zb-table/zb-table.vue
+1342
-0
package.json
uni_modules/zb-table/package.json
+81
-0
readme.md
uni_modules/zb-table/readme.md
+189
-0
No files found.
api/apiList.js
View file @
dcd21c31
...
...
@@ -123,6 +123,27 @@ export function getOrderPodSingList(data) {
return
Request
(
`/api/entry/{mini}/m-action/getOrderPodSingList`
,
data
);
}
//查询一级异常信息
export
function
getLevelAbnormalAll
(
data
)
{
return
Request
(
`/api/entry/{mini}/m-action/getLevelAbnormalAll`
,
data
);
}
//查询费用明细项
export
function
getAbnormaCostBaseAll
(
data
)
{
return
Request
(
`/api/entry/{mini}/m-action/getAbnormaCostBaseAll`
,
data
);
}
//查询币种
export
function
getCurrencyAll
(
data
)
{
return
Request
(
`/api/entry/{mini}/m-action/getCurrencyAll`
,
data
);
}
//新增异常费用信息
export
function
saveAppAbnormalEvent
(
data
)
{
return
Request
(
`/api/entry/{mini}/m-action/saveAppAbnormalEvent`
,
data
);
}
// 查询货量明细
// OM模式
export
function
OMOrderDetail
(
data
)
{
...
...
components/baseComponents/bs-todoRemark/bs-todoRemark.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"todo-remark"
>
<view
class=
"remark-title"
>
{{
title
}}
</view>
<u-textarea
v-model=
"value"
:placeholder=
"isReadonly ? '' : placeholder"
:count=
"!isReadonly"
autoHeight
:disabled=
"isReadonly"
maxlength=
"200"
border=
"none"
@
blur=
"onBlur"
holdKeyboard
/>
</view>
</
template
>
<
script
>
export
default
{
name
:
"bs-todoRemark"
,
options
:
{
styleIsolation
:
'shared'
},
props
:
{
title
:
{
type
:
String
,
default
:
""
},
placeholder
:
{
type
:
String
,
default
:
""
},
isReadonly
:
{
type
:
Boolean
,
default
:
false
}
},
data
()
{
return
{
value
:
""
};
},
methods
:
{
onBlur
(
e
)
{
const
{
value
}
=
e
.
detail
this
.
setValue
(
value
)
},
//设置默认值
setValue
(
value
)
{
this
.
value
=
value
}
}
}
</
script
>
<
style
lang=
"scss"
>
.todo-remark
{
font-size
:
28rpx
;
margin-top
:
32rpx
;
.remark-title
{
color
:
#8C8C8C
;
margin-bottom
:
24rpx
;
}
.u-textarea
{
min-height
:
150rpx
;
background-color
:
#FAFAFA
;
.u-textarea__field
{
min-height
:
120rpx
;
}
}
}
</
style
>
pages.json
View file @
dcd21c31
...
...
@@ -119,9 +119,9 @@
"enablePullDownRefresh"
:
false
}
},
{
"path"
:
"
signFor/signFor
"
,
"path"
:
"
abnormalEventDetail/abnormalEventDetail
"
,
"style"
:
{
"navigationBarTitleText"
:
""
,
"navigationBarTitleText"
:
"
费用明细
"
,
"enablePullDownRefresh"
:
false
,
"disableScroll"
:
false
}
...
...
@@ -151,7 +151,8 @@
"enablePullDownRefresh"
:
false
,
"disableScroll"
:
true
}
}]
}
]
}],
"globalStyle"
:
{
"navigationBarTextStyle"
:
"white"
,
...
...
pages/index/index.vue
View file @
dcd21c31
...
...
@@ -24,7 +24,7 @@
<view
class=
"section_9"
>
<u-button
@
click=
"warehouseShipment()"
shape=
"circle"
color=
"#2E75E6"
text=
"仓库已发货"
></u-button>
<u-button
@
click=
"arrivalPort()"
shape=
"circle"
color=
"#2E75E6"
text=
"进港(到目的地)"
customStyle=
"margin-left: 20rpx;"
></u-button>
<u-button
@
click=
"on
VisibleDate
()"
shape=
"circle"
color=
"#2E75E6"
customStyle=
"margin-left: 20rpx;"
text=
"异常上报"
></u-button>
<u-button
@
click=
"on
AbnormalEvents
()"
shape=
"circle"
color=
"#2E75E6"
customStyle=
"margin-left: 20rpx;"
text=
"异常上报"
></u-button>
</view>
</view>
<!--
<view
class=
"box_4"
>
...
...
@@ -231,6 +231,22 @@
})
}
},
//异常上报
onAbnormalEvents
(){
if
(
this
.
message
.
length
>
0
)
{
console
.
log
(
this
.
message
)
getApp
().
globalData
.
abnormalEvent
=
this
.
message
[
0
]
uni
.
navigateTo
({
url
:
`/subpkg/abnormalEvent/abnormalEvent`
,
})
}
else
{
uni
.
showToast
({
title
:
"请选择运单"
,
duration
:
3000
,
icon
:
'error'
})
}
},
//到厂、仓库到货、进港提交表单数据
onSubmitForm
(
type
)
{
const
rows
=
this
.
choose
;
...
...
subpkg/abnormalEvent/abnormalEvent.vue
View file @
dcd21c31
<
template
>
<view
class=
"abnormalEvent-list content_box"
>
<view
class=
"abnormalEvent-item"
>
<view
v-if=
"eventList.order_base_no!=null && eventList.shipment_no==null"
>
<bs-customCell
label=
"基础订单号 :"
:value=
"eventList.order_base_no"
labelCol=
"3"
wrapCol=
"6"
/>
</view>
<view
v-if=
"eventList.shipment_no!=null"
>
<bs-customCell
label=
"运单号 :"
:value=
"eventList.shipment_no"
labelCol=
"3"
wrapCol=
"6"
/>
</view>
<!-- 注册内容 -->
<u--form
:model=
"formData"
:rules=
"rules"
ref=
"myForm"
errorType=
'none'
>
<view
class=
"basic-info"
>
<u-form-item
prop=
"one_level_abnormal"
required
label=
"一级异常"
labelWidth=
"25%"
borderBottom
>
<view
@
click=
"showProcess"
>
<u-input
border=
"none"
readonly
placeholder=
"请选择一级异常"
:value=
"viewEnums[formData.one_level_abnormal]"
/>
</view>
</u-form-item>
<u-form-item
prop=
"two_level_abnormal"
label=
"二级异常"
labelWidth=
"25%"
borderBottom
>
<u-input
:disabledColor=
"'#ffffff'"
border=
"none"
v-model=
"formData.two_level_abnormal"
/>
</u-form-item>
<u-form-item
prop=
"occur_location"
label=
"发生地点"
labelWidth=
"25%"
borderBottom
>
<u-input
:disabledColor=
"'#ffffff'"
border=
"none"
v-model=
"formData.occur_location"
/>
</u-form-item>
<u-form-item
prop=
"occur_time"
label=
"发生时间"
labelWidth=
"35%"
borderBottom
>
<view
@
click=
"onVisibleDate('occur_time')"
>
<u-input
:disabledColor=
"'#ffffff'"
disabled
border=
"none"
readonly
placeholder=
"请选择发生时间"
:value=
"convertTime(formData.occur_time)"
/>
</view>
</u-form-item>
<u-form-item
prop=
"abnormal_reason"
label=
"异常原因"
labelWidth=
"25%"
borderBottom
>
<u-input
:disabledColor=
"'#ffffff'"
border=
"none"
v-model=
"formData.abnormal_reason"
/>
</u-form-item>
<u-form-item
prop=
"person_liable"
label=
"责任人"
labelWidth=
"25%"
borderBottom
>
<u-input
:disabledColor=
"'#ffffff'"
border=
"none"
v-model=
"formData.person_liable"
/>
</u-form-item>
</view>
<!-- 异常文件 -->
<view
class=
"uploader-img"
>
<bs-uploader
ref=
"myUploadImg"
:required=
"requiredStatus"
uploadTitle=
"异常文件"
/>
</view>
<view
class=
"module-title flex"
>
<text
class=
"font_bolder"
>
费用明细
</text>
<view
style=
"flex: 1;"
></view>
<div
style=
"display: flex; justify-content: flex-end;"
>
<u-button
@
click=
"onRateItemDatail()"
style=
"width: 100px;"
type=
"error"
size=
"small"
>
增加明细
</u-button>
</div>
</view>
<view
class=
"driverJobCertificate"
>
<zb-table
:show-header=
"true"
:columns=
"column"
:stripe=
"true"
:fit=
"false"
@
rowClick=
"rowClick"
@
toggleRowSelection=
"toggleRowSelection"
@
toggleAllSelection=
"toggleAllSelection"
:border=
"true"
@
edit=
"buttonEdit"
@
dele=
"dele"
:data=
"tableData"
:key=
"index"
></zb-table>
</view>
</u--form>
<!--查询一级异常-->
<u-popup
:show=
"visible"
@
close=
"closeProcess"
>
<view
class=
"select-container"
>
<view
class=
"search-input flex_center"
>
<u-search
searchIconSize=
"50"
searchIconColor=
"#FFFFFF"
placeholderColor=
'#757575'
color=
"#606266"
:showAction=
"false"
:placeholder=
"placeholder"
v-model=
"searchValue"
@
clickIcon=
"onSearch"
@
search=
"onSearch"
@
clear=
"onSearchclear"
/>
</view>
<scroll-view
scroll-y
class=
"select-list"
>
<u-radio-group
v-model=
"currentChecked"
placement=
"column"
iconPlacement=
"right"
>
<u-radio
:customStyle=
"
{margin: '22rpx 40rpx'}" :size="40" :iconSize="32" :labelSize="32"
labelColor="#262626" v-for="(item, index) in selectEnum" :key="index" :label="item.label"
:name="item.value" @change="onSelect(item.value)">
</u-radio>
</u-radio-group>
</scroll-view>
</view>
</u-popup>
</view>
<!-- 底部按钮 -->
<view
class=
"operation-btn flex_sb"
>
<button
class=
"backBtn common_btn"
@
click=
"onNavBack"
>
返回
</button>
<button
class=
"submitBtn common_btn"
@
click=
"onSubmitForm"
>
确认
</button>
</view>
<!-- 类型选择动作面板 -->
<bs-selectPopup
:popTitle=
"popTitle"
:selectEnum=
"optionEnums"
:visible=
"visible2"
@
onVisible=
"onVisible"
@
onConfirm=
"onConfirmPicker"
/>
<!-- 时间选择 -->
<bs-datetimePicker
ref=
"myTimePicker"
:visible=
"showPopup"
@
onVisible=
"onVisibleDate"
@
onSelsectDate=
"onSelsectDate"
/>
</view>
</
template
>
<
script
>
import
{
getLevelAbnormalAll
,
getAbnormaCostBaseAll
,
getCurrencyAll
,
saveAppAbnormalEvent
}
from
'../../api/apiList.js'
export
default
{
name
:
'abnormalEvent'
,
options
:
{
styleIsolation
:
'shared'
},
data
()
{
return
{
pageNum
:
1
,
//页码
pageSize
:
10
,
//每页条数
eventList
:
''
,
//头信息
tableData
:[],
isEmpty
:
true
,
//是否为空
rows
:
[],
//当前展开面板
formData
:
{
one_level_abnormal
:
''
,
//一级异常
two_level_abnormal
:
""
,
//二级异常
occur_location
:
""
,
//发生地点
occur_time
:
""
,
//发生时间
abnormal_reason
:
""
,
//异常原因
person_liable
:
""
,
//责任人
},
rules
:
{
'one_level_abnormal'
:
{
required
:
true
},
//一级异常
},
showPopup
:
false
,
//时间选择
visibleKey
:
''
,
//当前显示字段的key
optionEnums
:
[],
//候选项枚举
popTitle
:
''
,
//弹窗标题
visible
:
false
,
//一级异常类型选择
viewEnums
:[],
//一级异常枚举视图
searchValue
:
""
,
//搜索值--一级异常
selectEnum
:[],
//接受返回值
currentChecked
:
''
,
placeholder
:
"请输入搜索一级异常"
,
//默认提示
column
:
[{
name
:
'operation'
,
type
:
'operation'
,
align
:
'center'
,
label
:
'操作'
,
renders
:
[{
name
:
'编辑'
,
func
:
'edit'
// func 代表子元素点击的事件 父元素接收的事件 父元素 @edit
},
{
name
:
'删除'
,
type
:
'warn'
,
func
:
"dele"
},
]
},
{
name
:
'cost_classification_label'
,
label
:
'费用大类'
,
fixed
:
'true'
,
},
{
name
:
'rate_item'
,
label
:
'费用项'
},
{
name
:
'money'
,
label
:
'金额'
},
{
name
:
'currency'
,
label
:
'币种'
},{
name
:
'remark'
,
label
:
'备注'
},{
name
:
'files'
,
label
:
'文件'
},
],
}
},
onShow
()
{
const
newData
=
[];
const
data
=
getApp
().
globalData
.
abnormalEvent
const
td
=
getApp
().
globalData
.
tableData
;
this
.
eventList
=
data
;
if
(
td
)
{
if
(
td
.
change
)
{
this
.
tableData
.
map
(
item
=>
{
//费用项+币种是唯一的
if
(
item
.
rate_item
!=
td
.
rate_item
&&
item
.
currency
!=
currency
){
newData
.
push
(
item
)
}
})
newData
.
push
(
td
);
getApp
().
globalData
.
tableData
=
null
this
.
tableData
=
[]
this
.
tableData
=
newData
;
}
else
{
this
.
tableData
.
push
(
td
)
getApp
().
globalData
.
tableData
=
null
}
}
},
methods
:
{
dele
(
e
)
{
const
index
=
e
.
key
;
// 找到元素 e 的索引
if
(
index
!==
-
1
)
{
this
.
tableData
.
splice
(
index
,
1
);
// 移除该元素
}
},
buttonEdit
(
e
)
{
getApp
().
globalData
.
tableData
=
e
this
.
onRateItemDatail
();
},
//跳转费用明细新增
onRateItemDatail
()
{
getApp
().
globalData
.
all
=
this
.
tableData
;
//所有的明细
uni
.
navigateTo
({
url
:
`/subpkg/abnormalEventDetail/abnormalEventDetail`
,
})
},
//一级异常
showProcess
()
{
this
.
visible
=
true
},
//一级异常关闭弹出框
closeProcess
()
{
this
.
visible
=
false
this
.
selectEnum
=
[]
this
.
searchValue
=
''
},
//一级异常输入查询
onSearch
()
{
this
.
pageNum
=
1
this
.
onLevelAbnormal
()
},
onSelect
(
value
)
{
this
.
formData
.
one_level_abnormal
=
value
;
this
.
visible
=
false
},
//清除一级异常
onSearchclear
(){
this
.
selectEnum
=
[]
this
.
searchValue
=
''
},
//查询一级异常回调
onLevelAbnormal
(
type
)
{
const
{
pageNum
,
pageSize
}
=
this
const
executeBu
=
this
.
eventList
.
execute_bu
const
orderType
=
this
.
eventList
.
order_type
.
substring
(
0
,
2
);
let
optionEnums
=
[]
var
searchValue
=
this
.
searchValue
let
reqData
=
{
"args"
:
{
pageNum
,
pageSize
,
executeBu
,
orderType
}
}
if
(
this
.
searchValue
){
reqData
.
args
.
restrictions
=
[{
"field"
:
'des'
,
"type"
:
"like"
,
//EQ精准匹配,LK模糊匹配
"value"
:
this
.
searchValue
}]
}
let
_this
=
this
;
var
setKey
=
'viewEnums'
getLevelAbnormalAll
(
reqData
).
then
(
res
=>
{
uni
.
stopPullDownRefresh
()
optionEnums
=
res
.
data
.
data
.
datas
;
this
.
setViewEnums
(
optionEnums
,
setKey
)
_this
.
selectEnum
=
optionEnums
})
},
// 提交表单数据
onSubmitForm
()
{
const
rows
=
getApp
().
globalData
.
abnormalEvent
;
if
(
this
.
formData
.
one_level_abnormal
==
null
||
this
.
formData
.
one_level_abnormal
==
""
){
uni
.
showToast
({
title
:
"一级异常不能为空"
,
icon
:
'none'
,
duration
:
2000
})
return
;
}
this
.
formData
.
occur_time
=
this
.
formatDate
(
this
.
formData
.
occur_time
)
var
baseData
=
{
"aux"
:
{
"rows"
:
rows
,
"addEvent"
:
this
.
formData
,
"costList"
:
this
.
tableData
,
},
}
//新增异常操作
saveAppAbnormalEvent
(
baseData
).
then
(
res
=>
{
if
(
res
.
data
.
data
.
messageType
===
'success'
)
{
uni
.
showToast
({
title
:
'操作成功!'
,
duration
:
1000
})
setTimeout
(()
=>
{
uni
.
navigateBack
()
},
1500
)
}
})
},
//设置显示枚举
setViewEnums
(
optionEnums
,
key
)
{
let
viewEnums
=
{}
optionEnums
.
map
(
item
=>
{
viewEnums
[
item
.
value
]
=
item
.
label
})
this
[
key
]
=
viewEnums
},
//确认选择
onConfirmPicker
(
value
)
{
if
(
this
.
chooseType
==
'cost_classification'
)
{
var
index
=
this
.
chooseIndex
this
.
orderList
[
0
].
cargoDetails
[
index
].
cost_classification
=
value
}
else
{
this
.
setFormData
(
value
)
}
this
.
visible
=
false
this
.
visible2
=
false
},
//页面展示时间戳转换为日期
convertTime
(
timestamp
)
{
if
(
!
timestamp
)
return
const
nowDate
=
new
Date
(
timestamp
)
var
year
=
nowDate
.
getFullYear
();
var
month
=
nowDate
.
getMonth
()
+
1
;
var
date
=
nowDate
.
getDate
();
return
`
${
year
}
-
${
month
}
-
${
date
}
`
},
//时间戳转换
formatDate
(
timestamp
)
{
if
(
!
timestamp
)
return
const
nowDate
=
new
Date
(
timestamp
)
var
year
=
nowDate
.
getFullYear
();
var
month
=
nowDate
.
getMonth
()
<
10
?
'0'
+
(
nowDate
.
getMonth
()
+
1
)
:
nowDate
.
getMonth
()
+
1
;
var
date
=
nowDate
.
getDate
();
const
hour
=
nowDate
.
getHours
();
const
minute
=
nowDate
.
getMinutes
()
<
10
?
'0'
+
nowDate
.
getMinutes
()
:
nowDate
.
getMinutes
()
;
var
seconds
=
nowDate
.
getSeconds
()
<
10
?
'0'
+
nowDate
.
getSeconds
()
:
nowDate
.
getSeconds
();
if
(
this
.
dateType
===
'date'
)
{
return
`
${
year
}
-
${
month
}
-
${
date
}
`
}
else
{
return
`
${
year
}
-
${
month
}
-
${
date
}
${
hour
}
:
${
minute
}
:
${
seconds
}
`
}
},
//设置formData
setFormData
(
value
)
{
const
key
=
this
.
visibleKey
if
(
key
.
includes
(
'.'
))
{
//对象特殊处理
const
keys
=
key
.
split
(
'.'
)
this
.
formData
[
keys
[
0
]][
keys
[
1
]]
=
value
}
else
{
this
.
formData
[
key
]
=
value
}
},
// 时间选择
onSelsectDate
(
dateInfo
)
{
const
{
timestamp
}
=
dateInfo
this
.
setFormData
(
timestamp
)
this
.
showPopup
=
false
},
//关闭时间选择框
onVisibleDate
(
type
)
{
if
(
type
)
{
this
.
visibleKey
=
type
}
this
.
showPopup
=
!
this
.
showPopup
},
}
}
</
script
>
<
style
lang=
"scss"
>
.abnormalEvent-list
{
.module-title
{
margin-top
:
20rpx
;
.vertical-separate
{
height
:
40rpx
;
border-left
:
7rpx
solid
#797979
;
margin-right
:
20rpx
;
}
}
.select-container
{
min-width
:
70vw
;
height
:
50vh
;
padding
:
30rpx
;
font-weight
:
400
;
.popTitle
{
color
:
#8C8C8C
;
font-size
:
32rpx
;
text-align
:
center
;
margin-bottom
:
44rpx
;
}
.select-list
{
height
:
460rpx
;
}
}
.new_cost
{
background-color
:
coral
;
height
:
30px
;
width
:
100px
;
border-radius
:
5px
;
display
:
flex
;
justify-content
:
center
;
/* 水平居中 */
align-items
:
center
;
/* 垂直居中 */
margin-bottom
:
-10px
;
}
.abnormalEvent-item
{
padding
:
32rpx
;
margin-bottom
:
24rpx
;
background
:
#FFFFFF
;
.detail-title
{
font-size
:
28rpx
;
padding
:
8rpx
0
30rpx
;
border-bottom
:
1rpx
solid
#E5E5E5
;
.t-icon-order
{
width
:
50rpx
;
height
:
50rpx
;
margin-right
:
20rpx
;
}
}
/
deep
/
.custom-cell-row
{
margin-top
:
10rpx
;
.custom-cell-label
{
color
:
#8C8C8C
;
}
}
.outer-frame
{
margin-top
:
32rpx
;
border-radius
:
16rpx
;
border
:
2rpx
solid
#F0F0F0
;
overflow
:
hidden
;
.foldPanel-title
{
color
:
#2E75E6
;
font-size
:
28rpx
;
padding-left
:
20rpx
;
height
:
96rpx
;
background
:
rgba
(
46
,
117
,
230
,
.1
);
.foldPanel-right-icon
{
margin-right
:
20rpx
;
}
}
/
deep
/
.cargo-detail-table
{
background
:
#FFFFFF
;
padding-bottom
:
10rpx
;
.detail-row-title
{
color
:
#8C8C8C
;
background
:
#FAFAFA
;
padding
:
20rpx
0
;
}
.detail-col-item
{
margin
:
20rpx
;
.cargo-title
{
font-size
:
28rpx
;
padding-left
:
20rpx
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
}
}
}
.snapshoot
image
{
margin
:
20rpx
15rpx
;
width
:
140rpx
;
height
:
140rpx
;
}
/
deep
/
.basic-info
,
/
deep
/
.driving-license
{
padding
:
0
10rpx
;
background-color
:
#ffffff
;
.input-tip
{
font-size
:
28rpx
;
color
:
#BFBFBF
;
}
.u-form-item__body__left__content__label
{
color
:
#8C8C8C
;
font-size
:
28rpx
;
}
.u-form-item__body
{
padding
:
25rpx
0
;
}
.u-icon
{
margin-left
:
20rpx
;
}
.u-upload__wrap
>
view
{
width
:
100%
;
}
.previewImages
{
width
:
100%
;
.previewImg
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
}
}
.uploadeBtn
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
margin-bottom
:
30rpx
;
margin-left
:
0
!
important
;
}
.orderTotal
{
display
:
none
;
}
}
.outer-frame
{
border-radius
:
16rpx
;
border
:
2rpx
solid
#F0F0F0
;
overflow
:
hidden
;
.foldPanel-title
{
color
:
#2E75E6
;
font-size
:
28rpx
;
padding-left
:
20rpx
;
height
:
96rpx
;
background
:
rgba
(
46
,
117
,
230
,
.1
);
.foldPanel-right-icon
{
margin-right
:
20rpx
;
}
}
/
deep
/
.cargo-detail-table
{
background
:
#FFFFFF
;
padding-bottom
:
10rpx
;
.detail-row-title
{
color
:
#8C8C8C
;
background
:
#FAFAFA
;
padding
:
20rpx
0
;
}
.detail-col-item
{
margin
:
20rpx
;
.cargo-title
{
font-size
:
28rpx
;
padding-left
:
20rpx
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.u-number-box
{
justify-content
:
center
!
important
;
}
//步进器相关
.u-number-box__input
{
margin
:
0
10rpx
;
color
:
#333333
!
important
;
width
:
60rpx
!
important
;
height
:
40rpx
!
important
;
background-color
:
#fff
!
important
;
}
.u-number-box__minus
,
.u-number-box__plus
{
width
:
40rpx
;
height
:
40rpx
!
important
;
border-radius
:
6rpx
;
border
:
2rpx
solid
#C9C9C9
;
}
.uicon-plus
,
.uicon-minus
{
font-size
:
20rpx
!
important
;
}
}
}
/
deep
/
.basicInfo
,
/
deep
/
.driverLicense
,
/
deep
/
.driverJobCertificate
{
padding
:
0
40rpx
;
background-color
:
#ffffff
;
.input-tip
{
font-size
:
28rpx
;
color
:
#BFBFBF
;
}
.u-form-item__body__left__content__label
{
color
:
#8C8C8C
;
font-size
:
28rpx
;
}
.u-form-item__body
{
padding
:
40rpx
0
;
}
.u-icon
{
margin-left
:
20rpx
;
}
}
/
deep
/
.driverLicense-uploader-img
,
/
deep
/
.driverJobCertificate
{
.u-upload__wrap
>
view
{
width
:
100%
;
}
.previewImages
{
width
:
100%
;
.previewImg
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
}
}
.uploadeBtn
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
margin-bottom
:
30rpx
;
margin-left
:
0
!
important
;
}
.orderTotal
{
display
:
none
;
}
}
}
</
style
>
subpkg/abnormalEventDetail/abnormalEventDetail.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"abnormalEventDetail-list content_box"
>
<view
class=
"abnormalEventDetail-item"
>
<!-- 注册内容 -->
<u--form
:model=
"formData"
:rules=
"rules"
ref=
"myForm"
errorType=
'none'
>
<view
class=
"basic-info"
>
<u-form-item
prop=
"cost_classification"
required
label=
"费用大类"
labelWidth=
"25%"
borderBottom
>
<view
@
click=
"onVisible('cost_classification')"
>
<u-input
border=
"none"
readonly
placeholder=
"请选择费用大类"
:value=
"ficationViewEnums[formData.cost_classification]"
/>
</view>
</u-form-item>
<u-form-item
prop=
"rate_item"
required
label=
"费用项"
labelWidth=
"25%"
borderBottom
>
<view
@
click=
"showProcess3"
>
<u-input
border=
"none"
readonly
placeholder=
"请选择费用项"
:value=
"rateViewEnums[formData.rate_item]"
/>
</view>
</u-form-item>
<u-form-item
prop=
"money"
required
label=
"金额"
labelWidth=
"25%"
borderBottom
>
<u-input
:disabledColor=
"'#ffffff'"
border=
"none"
v-model=
"formData.money"
/>
</u-form-item>
<u-form-item
prop=
"currency"
required
label=
"币种"
labelWidth=
"25%"
borderBottom
>
<view
@
click=
"showProcess4"
>
<u-input
border=
"none"
readonly
placeholder=
"请选择币种"
:value=
"currencyViewEnums[formData.currency]"
/>
</view>
</u-form-item>
</view>
</u--form>
<!-- 异常文件 -->
<view
class=
"reported-detail"
>
<!-- 备注信息 -->
<bs-todoRemark
ref=
"myRemark"
title=
"备注"
/>
<!-- 上传图片 -->
<view
class=
"uploader-img"
>
<bs-uploader
ref=
"myUploadImg"
uploadTitle=
"拍照上传图片"
/>
</view>
</view>
<!--查询费用明细-->
<u-popup
:show=
"visible3"
@
close=
"closeProcess3"
>
<view
class=
"select-container"
>
<view
class=
"search-input flex_center"
>
<u-search
searchIconSize=
"50"
searchIconColor=
"#FFFFFF"
placeholderColor=
'#757575'
color=
"#606266"
:showAction=
"false"
:placeholder=
"placeholder3"
v-model=
"searchValue3"
@
clickIcon=
"onSearch3"
@
search=
"onSearch3"
@
clear=
"onSearchclear3"
/>
</view>
<scroll-view
scroll-y
class=
"select-list"
>
<u-radio-group
v-model=
"currentChecked"
placement=
"column"
iconPlacement=
"right"
>
<u-radio
:customStyle=
"
{margin: '22rpx 40rpx'}" :size="40" :iconSize="32" :labelSize="32"
labelColor="#262626" v-for="(item, index) in selectEnum3" :key="index" :label="item.label"
:name="item.value" @change="onSelect3(item.value, index)">
</u-radio>
</u-radio-group>
</scroll-view>
</view>
</u-popup>
<!--查询币种-->
<u-popup
:show=
"visible4"
@
close=
"closeProcess4"
>
<view
class=
"select-container"
>
<view
class=
"search-input flex_center"
>
<u-search
searchIconSize=
"50"
searchIconColor=
"#FFFFFF"
placeholderColor=
'#757575'
color=
"#606266"
:showAction=
"false"
:placeholder=
"placeholder4"
v-model=
"searchValue4"
@
clickIcon=
"onSearch4"
@
search=
"onSearch4"
@
clear=
"onSearchclear4"
/>
</view>
<scroll-view
scroll-y
class=
"select-list"
>
<u-radio-group
v-model=
"currentChecked"
placement=
"column"
iconPlacement=
"right"
>
<u-radio
:customStyle=
"
{margin: '22rpx 40rpx'}" :size="40" :iconSize="32" :labelSize="32"
labelColor="#262626" v-for="(item, index) in selectEnum4" :key="index" :label="item.label"
:name="item.value" @change="onSelect4(item.value, index)">
</u-radio>
</u-radio-group>
</scroll-view>
</view>
</u-popup>
</view>
<!-- 底部按钮 -->
<view
class=
"operation-btn flex_sb"
>
<button
class=
"backBtn common_btn"
@
click=
"onNavBack"
>
返回
</button>
<button
class=
"submitBtn common_btn"
@
click=
"onSubmitForm"
>
确认
</button>
</view>
<!-- 类型选择动作面板 -->
<bs-selectPopup
:popTitle=
"popTitle"
:selectEnum=
"optionEnums"
:visible=
"visible2"
@
onVisible=
"onVisible"
@
onConfirm=
"onConfirmPicker"
/>
<!-- 时间选择 -->
<bs-datetimePicker
ref=
"myTimePicker"
:visible=
"showPopup"
@
onVisible=
"onVisibleDate"
@
onSelsectDate=
"onSelsectDate"
/>
</view>
</
template
>
<
script
>
import
{
getAbnormaCostBaseAll
,
getCurrencyAll
}
from
'../../api/apiList.js'
export
default
{
name
:
'abnormalEventDetail'
,
options
:
{
styleIsolation
:
'shared'
},
data
()
{
return
{
pageNum
:
1
,
//页码
pageSize
:
10
,
//每页条数
eventList
:
''
,
//头信息
isEmpty
:
true
,
//是否为空
rows
:
[],
//当前展开面板
formData
:
{
cost_classification
:
''
,
//费用大类
cost_classification_label
:
''
,
rate_item
:
""
,
//费用项
money
:
""
,
//金额
currency
:
""
,
//币种
remark
:
""
,
//备注
files
:
""
,
//文件
},
rules
:
{
'cost_classification'
:
{
required
:
true
},
//费用大类
'rate_item'
:
{
required
:
true
},
//费用项
},
activeNames
:
[],
//当前展开面板 names => orderIds
showPopup
:
false
,
//时间选择
visibleKey
:
''
,
//当前显示字段的key
optionEnums
:
[],
//候选项枚举
popTitle
:
''
,
//弹窗标题
visible2
:
false
,
//费用大类
visible3
:
false
,
//费用项
visible4
:
false
,
//币种枚举
viewEnums
:[],
//一级异常枚举视图
ficationViewEnums
:[],
//费用大类项枚举
rateViewEnums
:[],
//费用项枚举
currencyViewEnums
:[],
//币种枚举
searchValue
:
""
,
//搜索值--一级异常
searchValue3
:
""
,
//搜索值--费用项
searchValue4
:
""
,
//币种
selectEnum
:[],
//接受返回值
selectEnum3
:[],
//接受返回值--费用项
selectEnum4
:[],
//币种
currentChecked
:
''
,
placeholder3
:
"请输入搜索费用项"
,
//默认提示
placeholder4
:
"请输入搜索币种"
,
//默认提示
ficationViewEnums
:
{
'cost_classification'
:
""
},
rateViewEnums
:
{
'rate_item'
:
""
},
currencyViewEnums
:
{
'currency'
:
""
},
}
},
onLoad
(
options
)
{
const
eventData
=
getApp
().
globalData
.
abnormalEvent
this
.
eventList
=
eventData
;
let
data
=
getApp
().
globalData
.
tableData
;
if
(
data
){
this
.
formData
=
data
this
.
ficationViewEnums
[
this
.
formData
.
cost_classification
]
=
this
.
formData
.
cost_classification_label
;
this
.
rateViewEnums
[
this
.
formData
.
rate_item
]
=
this
.
formData
.
rate_item
;
this
.
currencyViewEnums
[
this
.
formData
.
currency
]
=
this
.
formData
.
currency
;
this
.
formData
.
change
=
true
console
.
log
(
this
.
formData
.
change
)
}
},
methods
:
{
//费用项
showProcess3
(
indexs
)
{
this
.
chooseIndex
=
indexs
this
.
visible3
=
true
},
//费用项
showProcess4
(
indexs
)
{
this
.
chooseIndex
=
indexs
this
.
visible4
=
true
},
//费用项关闭弹出框
closeProcess3
()
{
this
.
visible3
=
false
this
.
selectEnum3
=
[]
this
.
searchValue3
=
''
},
//币种关闭弹出框
closeProcess4
()
{
this
.
visible4
=
false
this
.
selectEnum4
=
[]
this
.
searchValue4
=
''
},
//费用项输入查询
onSearch3
()
{
this
.
pageNum
=
1
this
.
onAbnormaCostBase
()
},
//币种输入查询
onSearch4
()
{
this
.
pageNum
=
1
this
.
onCurrencyAll
()
},
onSelect3
(
value
,
index
)
{
this
.
formData
.
rate_item
=
value
this
.
visible3
=
false
},
onSelect4
(
value
,
index
)
{
this
.
formData
.
currency
=
value
this
.
visible4
=
false
},
//清除费用项
onSearchclear3
(){
this
.
selectEnum3
=
[]
this
.
searchValue3
=
''
},
//清除币种
onSearchclear4
(){
this
.
selectEnum4
=
[]
this
.
searchValue4
=
''
},
//查询费用项目回调
onAbnormaCostBase
(
type
)
{
const
{
pageNum
,
pageSize
}
=
this
const
executeBu
=
this
.
eventList
.
execute_bu
let
optionEnums
=
[]
var
searchValue3
=
this
.
searchValue3
let
reqData
=
{
"args"
:
{
pageNum
,
pageSize
,
executeBu
}
}
if
(
this
.
searchValue3
){
reqData
.
args
.
restrictions
=
[{
"field"
:
'des'
,
"type"
:
"like"
,
//EQ精准匹配,LK模糊匹配
"value"
:
this
.
searchValue3
}]
}
let
_this
=
this
;
var
setKey
=
'rateViewEnums'
getAbnormaCostBaseAll
(
reqData
).
then
(
res
=>
{
uni
.
stopPullDownRefresh
()
optionEnums
=
res
.
data
.
data
.
datas
;
this
.
setViewEnums
(
optionEnums
,
setKey
)
_this
.
selectEnum3
=
optionEnums
})
},
//查询币种
onCurrencyAll
(
type
)
{
const
{
pageNum
,
pageSize
}
=
this
let
optionEnums
=
[]
var
searchValue4
=
this
.
searchValue4
let
reqData
=
{
"args"
:
{
pageNum
,
pageSize
}
}
if
(
this
.
searchValue4
){
reqData
.
args
.
restrictions
=
[{
"field"
:
'code'
,
"type"
:
"like"
,
//EQ精准匹配,LK模糊匹配
"value"
:
this
.
searchValue4
}]
}
let
_this
=
this
;
var
setKey
=
'currencyViewEnums'
getCurrencyAll
(
reqData
).
then
(
res
=>
{
uni
.
stopPullDownRefresh
()
optionEnums
=
res
.
data
.
data
.
datas
;
this
.
setViewEnums
(
optionEnums
,
setKey
)
_this
.
selectEnum4
=
optionEnums
})
},
//类型选择
async
onVisible
(
type
)
{
if
(
this
.
visible2
)
{
this
.
visible2
=
false
}
else
{
let
optionEnums
=
[]
let
setKey
=
'ficationViewEnums'
//要设置的字段Key
if
(
type
==
'cost_classification'
){
setKey
=
'ficationViewEnums'
//要设置的字段Key
optionEnums
=
[{
label
:
'基础费用'
,
value
:
'basic'
},
{
label
:
'额外费用'
,
value
:
'addition'
},
{
label
:
'异常费用'
,
value
:
'exception'
},
{
label
:
'补差费用'
,
value
:
'difference'
}]
}
this
.
setViewEnums
(
optionEnums
,
setKey
)
this
.
optionEnums
=
optionEnums
this
.
visibleKey
=
type
this
.
visible2
=
true
}
},
// 提交表单数据
onSubmitForm
()
{
const
imgInstance
=
this
.
$refs
.
myUploadImg
//获取图片上传实例
const
remarkInstance
=
this
.
$refs
.
myRemark
;
//备注
this
.
formData
.
remark
=
remarkInstance
.
value
;
imgInstance
.
uploadImage
(
images
=>
{
})
const
allData
=
getApp
().
globalData
.
all
;
//所有的明细
var
totle
=
0
;
if
(
allData
.
length
>
0
){
allData
.
map
(
item
=>
{
//费用项+币种是唯一的
if
(
item
.
rate_item
==
this
.
formData
.
rate_item
&&
item
.
currency
==
this
.
formData
.
currency
){
totle
+=
1
;
}
})
if
(
totle
>
0
){
uni
.
showToast
({
title
:
"已存相同的费用项和币种,请合并相同费用项和币种!"
,
icon
:
'none'
,
duration
:
2000
})
return
;
}
}
//验证金额
var
money
=
uni
.
$u
.
test
.
number
(
this
.
formData
.
money
)
if
(
!
money
)
{
uni
.
showToast
({
title
:
"请填写正确的金额"
,
icon
:
'none'
,
duration
:
2000
})
return
;
}
if
(
this
.
formData
.
rate_item
==
null
||
this
.
formData
.
rate_item
==
""
){
uni
.
showToast
({
title
:
"费用项不能为空"
,
icon
:
'none'
,
duration
:
2000
})
return
;
}
if
(
this
.
formData
.
currency
==
null
||
this
.
formData
.
currency
==
""
){
uni
.
showToast
({
title
:
"币种不能为空"
,
icon
:
'none'
,
duration
:
2000
})
return
;
}
var
cost
=
this
.
formData
.
cost_classification
;
if
(
cost
==
'basic'
){
this
.
formData
.
cost_classification_label
=
'基础费用'
}
else
if
(
cost
==
'addition'
){
this
.
formData
.
cost_classification_label
=
'额外费用'
}
else
if
(
cost
==
'exception'
){
this
.
formData
.
cost_classification_label
=
'异常费用'
}
else
if
(
cost
==
'difference'
){
this
.
formData
.
cost_classification_label
=
'补差费用'
}
getApp
().
globalData
.
tableData
=
this
.
formData
;
setTimeout
(()
=>
{
uni
.
navigateBack
()
},
1500
)
},
//返回上一级页面
onNavBack
()
{
setTimeout
(()
=>
{
uni
.
navigateBack
()
},
1500
)
},
//设置显示枚举
setViewEnums
(
optionEnums
,
key
)
{
let
viewEnums
=
{}
optionEnums
.
map
(
item
=>
{
viewEnums
[
item
.
value
]
=
item
.
label
})
this
[
key
]
=
viewEnums
},
//确认选择
onConfirmPicker
(
value
)
{
this
.
setFormData
(
value
)
this
.
visible
=
false
this
.
visible2
=
false
},
//页面展示时间戳转换为日期
convertTime
(
timestamp
)
{
if
(
!
timestamp
)
return
const
nowDate
=
new
Date
(
timestamp
)
var
year
=
nowDate
.
getFullYear
();
var
month
=
nowDate
.
getMonth
()
+
1
;
var
date
=
nowDate
.
getDate
();
return
`
${
year
}
-
${
month
}
-
${
date
}
`
},
//设置formData
setFormData
(
value
)
{
const
key
=
this
.
visibleKey
if
(
key
.
includes
(
'.'
))
{
//对象特殊处理
const
keys
=
key
.
split
(
'.'
)
this
.
formData
[
keys
[
0
]][
keys
[
1
]]
=
value
}
else
{
this
.
formData
[
key
]
=
value
}
},
// 时间选择
onSelsectDate
(
dateInfo
)
{
const
{
timestamp
}
=
dateInfo
this
.
setFormData
(
timestamp
)
this
.
showPopup
=
false
},
//关闭时间选择框
onVisibleDate
(
type
)
{
if
(
type
)
{
this
.
visibleKey
=
type
}
this
.
showPopup
=
!
this
.
showPopup
},
}
}
</
script
>
<
style
lang=
"scss"
>
.abnormalEventDetail-list
{
.module-title
{
margin-top
:
20rpx
;
//padding: 15rpx 0rpx 16rpx;
//background-color:#a2a2a2;
.vertical-separate
{
height
:
40rpx
;
border-left
:
7rpx
solid
#797979
;
margin-right
:
20rpx
;
}
}
.select-container
{
min-width
:
70vw
;
height
:
50vh
;
padding
:
30rpx
;
font-weight
:
400
;
.popTitle
{
color
:
#8C8C8C
;
font-size
:
32rpx
;
text-align
:
center
;
margin-bottom
:
44rpx
;
}
.select-list
{
height
:
460rpx
;
}
}
.new_cost
{
background-color
:
coral
;
height
:
30px
;
width
:
100px
;
border-radius
:
5px
;
display
:
flex
;
justify-content
:
center
;
/* 水平居中 */
align-items
:
center
;
/* 垂直居中 */
margin-bottom
:
-10px
;
}
.abnormalEventDetail-item
{
padding
:
32rpx
;
margin-bottom
:
24rpx
;
background
:
#FFFFFF
;
.detail-title
{
font-size
:
28rpx
;
padding
:
8rpx
0
30rpx
;
border-bottom
:
1rpx
solid
#E5E5E5
;
.t-icon-order
{
width
:
50rpx
;
height
:
50rpx
;
margin-right
:
20rpx
;
}
}
/
deep
/
.custom-cell-row
{
margin-top
:
10rpx
;
.custom-cell-label
{
color
:
#8C8C8C
;
}
}
.outer-frame
{
margin-top
:
32rpx
;
border-radius
:
16rpx
;
border
:
2rpx
solid
#F0F0F0
;
overflow
:
hidden
;
.foldPanel-title
{
color
:
#2E75E6
;
font-size
:
28rpx
;
padding-left
:
20rpx
;
height
:
96rpx
;
background
:
rgba
(
46
,
117
,
230
,
.1
);
.foldPanel-right-icon
{
margin-right
:
20rpx
;
}
}
/
deep
/
.cargo-detail-table
{
background
:
#FFFFFF
;
padding-bottom
:
10rpx
;
.detail-row-title
{
color
:
#8C8C8C
;
background
:
#FAFAFA
;
padding
:
20rpx
0
;
}
.detail-col-item
{
margin
:
20rpx
;
.cargo-title
{
font-size
:
28rpx
;
padding-left
:
20rpx
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
}
}
}
.snapshoot
image
{
margin
:
20rpx
15rpx
;
width
:
140rpx
;
height
:
140rpx
;
}
/
deep
/
.basic-info
,
/
deep
/
.driving-license
{
padding
:
0
10rpx
;
background-color
:
#ffffff
;
.input-tip
{
font-size
:
28rpx
;
color
:
#BFBFBF
;
}
.u-form-item__body__left__content__label
{
color
:
#8C8C8C
;
font-size
:
28rpx
;
}
.u-form-item__body
{
padding
:
25rpx
0
;
}
.u-icon
{
margin-left
:
20rpx
;
}
.u-upload__wrap
>
view
{
width
:
100%
;
}
.previewImages
{
width
:
100%
;
.previewImg
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
}
}
.uploadeBtn
{
width
:
100%
!
important
;
height
:
240rpx
!
important
;
margin-bottom
:
30rpx
;
margin-left
:
0
!
important
;
}
.orderTotal
{
display
:
none
;
}
}
.outer-frame
{
border-radius
:
16rpx
;
border
:
2rpx
solid
#F0F0F0
;
overflow
:
hidden
;
.foldPanel-title
{
color
:
#2E75E6
;
font-size
:
28rpx
;
padding-left
:
20rpx
;
height
:
96rpx
;
background
:
rgba
(
46
,
117
,
230
,
.1
);
.foldPanel-right-icon
{
margin-right
:
20rpx
;
}
}
/
deep
/
.cargo-detail-table
{
background
:
#FFFFFF
;
padding-bottom
:
10rpx
;
.detail-row-title
{
color
:
#8C8C8C
;
background
:
#FAFAFA
;
padding
:
20rpx
0
;
}
.detail-col-item
{
margin
:
20rpx
;
.cargo-title
{
font-size
:
28rpx
;
padding-left
:
20rpx
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.u-number-box
{
justify-content
:
center
!
important
;
}
//步进器相关
.u-number-box__input
{
margin
:
0
10rpx
;
color
:
#333333
!
important
;
width
:
60rpx
!
important
;
height
:
40rpx
!
important
;
background-color
:
#fff
!
important
;
}
.u-number-box__minus
,
.u-number-box__plus
{
width
:
40rpx
;
height
:
40rpx
!
important
;
border-radius
:
6rpx
;
border
:
2rpx
solid
#C9C9C9
;
}
.uicon-plus
,
.uicon-minus
{
font-size
:
20rpx
!
important
;
}
}
}
}
</
style
>
subpkg/signFor/signFor.vue
deleted
100644 → 0
View file @
c02bee8e
<
template
>
<view
class=
"signFor content_box"
>
<view
class=
"shipmentBriefInfo"
>
<bs-pageHeader-orderNo
:shipmentNo=
"shipmentInfo.header.shipmentNo"
/>
<view
class=
"primary-info routine_radius_card flex_center"
>
<view
style=
"width: 100%;"
>
<bs-customCell
label=
"货量 :"
labelCol=
"2"
wrapCol=
"10"
:value=
"shipmentInfo.header.shipOrders + '单/' +shipmentInfo.header.shipQty+ '件/' + shipmentInfo.header.shipWeight+'千克/'+ shipmentInfo.header.shipVolume+'方'"
/>
</view>
</view>
</view>
<!-- 订单信息 -->
<view
class=
"orders-total"
>
<view
class=
"orderQty font_bolder"
>
订单总数:
{{
orderList
.
length
}}
</view>
<scroll-view
class=
"order-detail-list"
scroll-y
>
<u-empty
mode=
"data"
textSize=
'32'
iconSize=
"160"
text=
"暂无订单"
v-if=
"!orderList.length"
/>
<u-checkbox-group
placement=
"column"
v-model=
"orderCheckeds"
>
<view
class=
"order-detail-item"
v-for=
"(item,index) in orderList"
:key=
"index"
>
<view
class=
"orderNo flex_sb"
>
<text>
订单号 :
{{
item
.
orderNo
}}
</text>
<u-checkbox
size=
'43'
:disabled=
"item.disabled"
iconSize=
'43'
:name=
"item.id"
/>
</view>
<u-line
color=
"#F0F0F0"
margin=
"20rpx 0"
/>
<view
class=
"cargoQty"
>
<text>
货量 :
</text>
<text
style=
"margin-left: 30rpx;"
>
{{
item
.
qty
}}
件 /
</text>
<text
style=
"margin-left: 20rpx;"
>
{{
item
.
weight
}}
千克 /
</text>
<text
style=
"margin-left: 20rpx;"
>
{{
item
.
volume
}}
方
</text>
</view>
<template
v-if=
"orderCheckeds.some(itm => itm === item.id)"
>
<!-- 异常选择 -->
<view
class=
"abnormal-select flex_sb flex_center"
>
<text>
是否异常
</text>
<switch
:checked=
"item.abnormal"
size=
"43"
color=
"#EB2F48"
style=
"transform:scale(0.8);width: 92rpx;"
@
change=
"onChange(item.id)"
/>
</view>
<!-- 备注信息 -->
<view
class=
"remark-content"
>
<u-textarea
border=
"none"
placeholder=
"请输入备注"
v-model=
"item.content"
holdKeyboard
/>
<!-- 图片上传 -->
<block>
<view
class=
"uploader-imgList flex flex_wrap"
>
<view
style=
"position: absolute;left: -14rpx;color: red;"
>
*
</view>
<view
class=
"previewImages"
v-for=
"(itm,idx) in item.images"
:key=
"idx"
>
<image
mode=
"aspectFill"
:src=
"itm"
@
click=
"onPreviewImage(idx, item.images)"
class=
"previewImg"
/>
<u-icon
name=
"close-circle-fill"
class=
"clearIcon"
size=
"30"
@
click=
"deleteImage(idx, item)"
/>
</view>
<!--
<view
v-if=
"!item.images.length"
style=
" width: 200rpx"
/>
-->
<template
v-if=
"isIos"
>
<view
class=
"uploadeBtn flex_col"
@
click=
"onUpLoad(item.id)"
>
<view
class=
"t-icon t-icon-picture"
/>
<text
style=
"margin-top:6rpx"
>
上传照片
</text>
<text
class=
"font_bolder orderTotal"
>
(
{{
item
.
images
.
length
}}
/6)
</text>
</view>
</
template
>
<
template
v-else
>
<u-upload
:fileList=
"item.images"
:max-count=
"6"
multiple
:previewImage=
"false"
:sizeType=
"['compressed']"
@
afterRead=
"uploadAfterRead"
:name=
"item.id"
>
<!-- 自定义上传按钮 -->
<view
class=
"uploadeBtn flex_col"
>
<view
class=
"t-icon t-icon-picture"
/>
<text
style=
"margin-top:6rpx"
>
上传照片
</text>
<text
class=
"font_bolder orderTotal"
>
(
{{
item
.
images
.
length
}}
/6)
</text>
</view>
</u-upload>
</
template
>
</view>
</block>
</view>
</template>
</view>
</u-checkbox-group>
</scroll-view>
</view>
<!-- 底部按钮 -->
<view
class=
"operation-btn flex_sb"
>
<button
class=
"backBtn common_btn"
@
click=
"onNavBack"
>
取消
</button>
<button
class=
"submitBtn common_btn"
@
click=
"onSubmit"
>
确定
</button>
</view>
</view>
</template>
<
script
>
import
{
signFor
,
uploadImg
,
ordermovementOM
,
ordermovementOR
,
ordermovementMASS
}
from
'../../api/apiList'
const
getUserLocation
=
require
(
'../../mixins/getUserLocation'
)
const
appInstance
=
getApp
()
export
default
{
mixins
:
[
getUserLocation
],
data
()
{
return
{
orderList
:
[],
//订单列表
orderCheckeds
:
[],
//已选中签收列表
isIos
:
false
,
shipmentInfo
:
{},
shipmentMode
:
''
,
// 运输模式 OM、OR、MS: 大宗运输Mass
}
},
onLoad
:
function
(
options
)
{
let
data
=
JSON
.
parse
(
options
.
data
)
const
{
shipmentData
}
=
data
this
.
shipmentInfo
=
shipmentData
const
title
=
'纸质签收'
const
{
shipmentId
,
shipmentBizName
}
=
appInstance
.
globalData
.
shipmentInfo
let
shipmentMode
=
''
switch
(
shipmentBizName
)
{
//根据shipmentBizName 判断运输模式
case
'tm.MovementShipment'
:
case
'tm.SectionShipment'
:
//暂时走OM逻辑
shipmentMode
=
'OM'
break
case
'tm.MassShipment'
:
shipmentMode
=
'MS'
;
//大宗运输
break
default
:
shipmentMode
=
'OR'
;
}
this
.
shipmentMode
=
shipmentMode
this
.
initData
(
shipmentId
)
this
.
setNavTitle
(
title
)
// #ifdef H5
const
platform
=
uni
.
getSystemInfoSync
().
platform
if
(
platform
===
'ios'
)
{
// this.isIos = true
}
// #endif
this
.
getUserSetting
()
},
methods
:
{
//设置页面头部标题
setNavTitle
(
title
)
{
uni
.
setNavigationBarTitle
({
title
:
title
,
})
},
//返回上一级页面
onNavBack
()
{
uni
.
navigateBack
()
},
//初始化数据
initData
(
shipmentId
)
{
let
newDatas
=
[]
if
(
this
.
shipmentMode
===
'MS'
)
{
const
reqData
=
{
"aux"
:
{
"id"
:
shipmentId
}
}
ordermovementMASS
(
reqData
).
then
(
res
=>
{
const
data
=
res
.
data
.
data
.
header
newDatas
.
push
({
'id'
:
data
[
'massOrder.id'
],
//订单id
'orderNo'
:
data
[
'massOrder.orderNo'
],
//订单号
'qty'
:
data
[
'massOrder.qty'
],
//订单件数
'weight'
:
data
[
'massOrder.weight'
],
//订单重量
'volume'
:
data
[
'massOrder.volume'
],
//订单体积
'abnormal'
:
false
,
//订单是否异常
'images'
:
[],
//订单图片
'content'
:
''
,
//订单备注信息
'disabled'
:
item
.
transportStatus
===
'80.POD'
//已签收时禁用
})
this
.
orderList
=
[...
newDatas
]
})
}
else
{
const
reqData
=
{
"args"
:
{
"pageNum"
:
1
,
"pageSize"
:
100
,
"restrictions"
:
[{
"field"
:
"shipment.id"
,
"type"
:
"EQ"
,
"value"
:
shipmentId
}]
}
}
const
isOM
=
this
.
shipmentMode
===
'OM'
const
requestFun
=
isOM
?
ordermovementOM
:
ordermovementOR
requestFun
(
reqData
).
then
(
res
=>
{
const
datas
=
res
.
data
.
data
.
datas
datas
.
map
(
item
=>
{
newDatas
.
push
({
'id'
:
item
.
id
,
//订单id
'orderNo'
:
isOM
?
item
.
movementNo
:
item
.
orderNo
,
//订单号
'qty'
:
isOM
?
item
.
shipQty
:
item
.
qty
,
//订单件数
'weight'
:
isOM
?
item
.
shipWeight
:
item
.
weight
,
//订单重量
'volume'
:
isOM
?
item
.
shipVolume
:
item
.
volume
,
//订单体积
'abnormal'
:
false
,
//订单是否异常
'images'
:
[],
//订单图片
'content'
:
''
,
//订单备注信息
'disabled'
:
item
.
transportStatus
===
'80.POD'
//已签收时禁用
})
})
this
.
orderList
=
[...
newDatas
]
})
}
},
// 确认
onSubmit
()
{
const
_this
=
this
let
{
orderList
,
orderCheckeds
}
=
_this
if
(
!
orderCheckeds
.
length
)
{
//校验是否存在可签收订单
this
.
customTost
()
return
}
//校验签收订单图片是否上传
let
flags
=
[]
orderCheckeds
.
map
(
checkOrderId
=>
{
let
order
=
orderList
.
find
(
orderItem
=>
orderItem
.
id
===
checkOrderId
)
if
(
!
order
.
images
.
length
)
{
flags
.
push
(
order
.
orderNo
)
}
})
if
(
flags
.
length
){
uni
.
showToast
({
title
:
`订单
${
flags
.
join
(
'|'
)}
图片信息不能为空`
,
icon
:
'none'
,
duration
:
3000
})
return
}
//调用接口签收订单
orderCheckeds
.
map
(
checkOrderId
=>
{
let
order
=
orderList
.
find
(
orderItem
=>
orderItem
.
id
===
checkOrderId
)
_this
.
uploadImages
(
order
.
images
,
imgs
=>
{
_this
.
onSignFor
(
order
,
imgs
)
//签收选中订单
})
})
},
//订单签收
onSignFor
(
orderData
,
images
)
{
const
{
longitude
,
latitude
,
address
,
time
}
=
this
.
locationInfo
const
reqData
=
{
'aux'
:
{
images
:
images
,
content
:
orderData
.
content
,
//备注
abnormal
:
orderData
.
abnormal
,
//是否异常
eventSource
:
'DriverApp'
,
longitude
,
latitude
,
address
,
time
},
"args"
:
{
"selectedIds"
:
[
orderData
.
id
]
}
}
const
signMode
=
{
'OM'
:
'OrderMovement'
,
'OR'
:
'SimpleOrder'
}
signFor
(
signMode
[
this
.
shipmentMode
],
reqData
).
then
(
res
=>
{
if
(
res
.
data
.
messageType
===
'success'
)
{
uni
.
showToast
({
title
:
'操作成功'
,
duration
:
3000
})
setTimeout
(()
=>
{
this
.
onNavBack
()
},
1500
)
}
})
},
onChange
(
orderId
){
const
newList
=
this
.
orderList
.
map
(
item
=>
{
if
(
item
.
id
===
orderId
){
item
.
abnormal
=
!
item
.
abnormal
}
return
item
})
this
.
orderList
=
[...
newList
]
},
//图片上传 IOS兼容
onUpLoad
(
orderId
)
{
if
(
this
.
$jwx
)
{
const
_this
=
this
const
sourceType
=
this
.
isIos
?
[
'album'
]
:
[
'album'
,
'camera'
]
// 可以指定来源是相册还是相机, ios指定为仅相册
this
.
$jwx
.
chooseImage
({
sizeType
:
[
'original'
,
'compressed'
],
// 可以指定是原图还是压缩图,默认二者都有
sourceType
:
sourceType
,
success
:
function
(
res
)
{
_this
.
onConvert
(
res
.
localIds
)
_this
.
orderItemId
=
orderId
}
})
}
},
async
onConvert
(
localIds
)
{
for
(
var
i
=
0
;
i
<
localIds
.
length
;
i
++
)
{
await
this
.
onReadImage
(
localIds
[
i
]);
}
},
onReadImage
(
localId
)
{
const
_this
=
this
return
new
Promise
((
resolve
,
reject
)
=>
{
_this
.
$jwx
.
getLocalImgData
({
localId
:
localId
,
// 图片的localID
success
:
function
(
res
)
{
const
localData
=
res
.
localData
let
orderList
=
_this
.
orderList
orderList
.
forEach
(
order
=>
{
if
(
order
.
id
===
_this
.
orderItemId
)
{
order
.
images
=
[...
order
.
images
,
localData
]
}
return
})
_this
.
orderList
=
[...
orderList
]
resolve
(
'done!'
)
}
});
})
},
//上传图片
uploadImages
(
fileList
,
callback
)
{
let
images
=
[]
fileList
.
forEach
(
item
=>
{
uploadImg
(
item
).
then
(
res
=>
{
uni
.
hideLoading
()
let
data
=
JSON
.
parse
(
res
).
data
images
.
push
(
data
.
path
)
if
(
images
.
length
===
fileList
.
length
)
{
return
callback
(
images
.
join
(
'|'
))
}
}).
catch
(
err
=>
{
console
.
log
(
err
);
})
})
},
// 自定义轻提示
customTost
()
{
uni
.
showToast
({
title
:
'暂无可签收订单'
,
icon
:
'none'
,
duration
:
3000
})
},
// 上传图片回调
uploadAfterRead
(
info
)
{
const
{
file
,
name
}
=
info
const
newFile
=
file
.
map
(
item
=>
item
.
url
);
let
orderList
=
this
.
orderList
orderList
.
forEach
(
order
=>
{
if
(
order
.
id
===
name
)
{
order
.
images
=
[...
order
.
images
,
...
newFile
]
}
return
})
this
.
orderList
=
[...
orderList
]
},
// 预览图片回调
onPreviewImage
(
index
,
images
)
{
uni
.
previewImage
({
current
:
index
,
urls
:
images
})
},
// 删除已选图片
deleteImage
(
index
,
info
)
{
let
orderList
=
this
.
orderList
uni
.
showModal
({
title
:
'删除提示'
,
content
:
'确定删除本张图片吗?'
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
orderList
.
forEach
(
order
=>
{
if
(
order
.
id
===
info
.
id
)
{
let
images
=
[...
order
.
images
]
images
.
splice
(
index
,
1
)
order
.
images
=
[...
images
]
}
return
})
this
.
orderList
=
[...
orderList
]
}
else
if
(
res
.
cancel
)
{}
}
})
},
}
}
</
script
>
<
style
lang=
"scss"
>
.orders-total
{
font-size
:
28rpx
;
background
:
#FAFAFA
;
.orderQty
{
padding
:
26rpx
30rpx
;
}
.order-detail-list
{
height
:
800rpx
;
.order-detail-item
{
width
:
100vw
;
margin-bottom
:
35rpx
;
padding
:
30rpx
;
background-color
:
#FFFFFF
;
/
deep
/
.orderNo
{
color
:
#8C8C8C
;
margin-bottom
:
30rpx
;
.u-checkbox__icon-wrap
{
margin-right
:
0
;
}
}
.abnormal-select
{
margin-top
:
30rpx
;
}
.remark-content
{
margin-top
:
30rpx
;
padding
:
16rpx
;
background
:
#FAFAFA
;
border-radius
:
8px
;
/
deep
/
.u-textarea
{
background
:
#FAFAFA
;
}
.uploader-imgList
{
padding-top
:
20rpx
;
position
:
relative
;
.previewImages
{
position
:
relative
;
overflow
:
hidden
;
.previewImg
{
width
:
180rpx
;
height
:
140rpx
;
margin
:
0
10rpx
20rpx
;
}
/
deep
/
.uicon-close-circle-fill
{
width
:
26rpx
;
height
:
26rpx
;
border-radius
:
50%
;
background-color
:
#fff
;
color
:
#D81E06
!
important
;
position
:
absolute
;
top
:
5rpx
!
important
;
right
:
15rpx
;
}
}
.uploadeBtn
{
position
:
relative
;
color
:
#929292
;
width
:
180rpx
;
height
:
140rpx
;
border
:
2rpx
dashed
#D9D9D9
;
margin
:
0
0
20rpx
6rpx
;
background-color
:
#fff
;
justify-content
:
center
;
align-items
:
center
;
font-size
:
24rpx
;
.orderTotal
{
color
:
#333333
;
position
:
absolute
;
right
:
-90rpx
;
bottom
:
0
;
z-index
:
999
;
}
.t-icon-picture
{
width
:
50rpx
;
height
:
50rpx
;
}
}
}
}
}
}
}
.primary-info
{
flex-wrap
:
wrap
;
.left-icon
{
position
:
relative
;
margin-right
:
20rpx
;
.leftIcon-text
{
font-size
:
28rpx
;
display
:
inline-block
;
position
:
absolute
;
top
:
5px
;
left
:
12px
;
}
.t-icon
{
width
:
70rpx
;
height
:
70rpx
;
}
}
/
deep
/
.custom-cell-row
{
width
:
100%
;
margin-top
:
32rpx
;
color
:
#8C8C8C
;
}
}
</
style
>
uni_modules/uni-table/changelog.md
0 → 100644
View file @
dcd21c31
## 1.2.1(2022-06-06)
-
修复 微信小程序存在无使用组件的问题
## 1.2.0(2021-11-19)
-
优化 组件UI,并提供设计资源,详见:
[
https://uniapp.dcloud.io/component/uniui/resource
](
https://uniapp.dcloud.io/component/uniui/resource
)
-
文档迁移,详见:
[
https://uniapp.dcloud.io/component/uniui/uni-table
](
https://uniapp.dcloud.io/component/uniui/uni-table
)
## 1.1.0(2021-07-30)
-
组件兼容 vue3,如何创建vue3项目,详见
[
uni-app 项目支持 vue3 介绍
](
https://ask.dcloud.net.cn/article/37834
)
## 1.0.7(2021-07-08)
-
新增 uni-th 支持 date 日期筛选范围
## 1.0.6(2021-07-05)
-
新增 uni-th 支持 range 筛选范围
## 1.0.5(2021-06-28)
-
新增 uni-th 筛选功能
## 1.0.4(2021-05-12)
-
新增 示例地址
-
修复 示例项目缺少组件的Bug
## 1.0.3(2021-04-16)
-
新增 sortable 属性,是否开启单列排序
-
优化 表格多选逻辑
## 1.0.2(2021-03-22)
-
uni-tr 添加 disabled 属性,用于 type=selection 时,设置某行是否可由全选按钮控制
## 1.0.1(2021-02-05)
-
调整为uni_modules目录规范
uni_modules/uni-table/components/uni-table/uni-table.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"uni-table-scroll"
:class=
"
{ 'table--border': border, 'border-none': !noData }">
<!-- #ifdef H5 -->
<table
class=
"uni-table"
border=
"0"
cellpadding=
"0"
cellspacing=
"0"
:class=
"
{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
<slot></slot>
<view
v-if=
"noData"
class=
"uni-table-loading"
>
<view
class=
"uni-table-text"
:class=
"
{ 'empty-border': border }">
{{
emptyText
}}
</view>
</view>
<view
v-if=
"loading"
class=
"uni-table-mask"
:class=
"
{ 'empty-border': border }">
<div
class=
"uni-table--loader"
></div></view>
</table>
<!-- #endif -->
<!-- #ifndef H5 -->
<view
class=
"uni-table"
:style=
"
{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }">
<slot></slot>
<view
v-if=
"noData"
class=
"uni-table-loading"
>
<view
class=
"uni-table-text"
:class=
"
{ 'empty-border': border }">
{{
emptyText
}}
</view>
</view>
<view
v-if=
"loading"
class=
"uni-table-mask"
:class=
"
{ 'empty-border': border }">
<div
class=
"uni-table--loader"
></div></view>
</view>
<!-- #endif -->
</view>
</
template
>
<
script
>
/**
* Table 表格
* @description 用于展示多条结构类似的数据
* @tutorial https://ext.dcloud.net.cn/plugin?id=3270
* @property {Boolean} border 是否带有纵向边框
* @property {Boolean} stripe 是否显示斑马线
* @property {Boolean} type 是否开启多选
* @property {String} emptyText 空数据时显示的文本内容
* @property {Boolean} loading 显示加载中
* @event {Function} selection-change 开启多选时,当选择项发生变化时会触发该事件
*/
export
default
{
name
:
'uniTable'
,
options
:
{
virtualHost
:
true
},
emits
:[
'selection-change'
],
props
:
{
data
:
{
type
:
Array
,
default
()
{
return
[]
}
},
// 是否有竖线
border
:
{
type
:
Boolean
,
default
:
false
},
// 是否显示斑马线
stripe
:
{
type
:
Boolean
,
default
:
false
},
// 多选
type
:
{
type
:
String
,
default
:
''
},
// 没有更多数据
emptyText
:
{
type
:
String
,
default
:
'没有更多数据'
},
loading
:
{
type
:
Boolean
,
default
:
false
},
rowKey
:
{
type
:
String
,
default
:
''
}
},
data
()
{
return
{
noData
:
true
,
minWidth
:
0
,
multiTableHeads
:
[]
}
},
watch
:
{
loading
(
val
)
{},
data
(
newVal
)
{
let
theadChildren
=
this
.
theadChildren
let
rowspan
=
1
if
(
this
.
theadChildren
)
{
rowspan
=
this
.
theadChildren
.
rowspan
}
// this.trChildren.length - rowspan
this
.
noData
=
false
// this.noData = newVal.length === 0
}
},
created
()
{
// 定义tr的实例数组
this
.
trChildren
=
[]
this
.
thChildren
=
[]
this
.
theadChildren
=
null
this
.
backData
=
[]
this
.
backIndexData
=
[]
},
methods
:
{
isNodata
()
{
let
theadChildren
=
this
.
theadChildren
let
rowspan
=
1
if
(
this
.
theadChildren
)
{
rowspan
=
this
.
theadChildren
.
rowspan
}
this
.
noData
=
this
.
trChildren
.
length
-
rowspan
<=
0
},
/**
* 选中所有
*/
selectionAll
()
{
let
startIndex
=
1
let
theadChildren
=
this
.
theadChildren
if
(
!
this
.
theadChildren
)
{
theadChildren
=
this
.
trChildren
[
0
]
}
else
{
startIndex
=
theadChildren
.
rowspan
-
1
}
let
isHaveData
=
this
.
data
&&
this
.
data
.
length
.
length
>
0
theadChildren
.
checked
=
true
theadChildren
.
indeterminate
=
false
this
.
trChildren
.
forEach
((
item
,
index
)
=>
{
if
(
!
item
.
disabled
)
{
item
.
checked
=
true
if
(
isHaveData
&&
item
.
keyValue
)
{
const
row
=
this
.
data
.
find
(
v
=>
v
[
this
.
rowKey
]
===
item
.
keyValue
)
if
(
!
this
.
backData
.
find
(
v
=>
v
[
this
.
rowKey
]
===
row
[
this
.
rowKey
]))
{
this
.
backData
.
push
(
row
)
}
}
if
(
index
>
(
startIndex
-
1
)
&&
this
.
backIndexData
.
indexOf
(
index
-
startIndex
)
===
-
1
)
{
this
.
backIndexData
.
push
(
index
-
startIndex
)
}
}
})
// this.backData = JSON.parse(JSON.stringify(this.data))
this
.
$emit
(
'selection-change'
,
{
detail
:
{
value
:
this
.
backData
,
index
:
this
.
backIndexData
}
})
},
/**
* 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)
*/
toggleRowSelection
(
row
,
selected
)
{
// if (!this.theadChildren) return
row
=
[].
concat
(
row
)
this
.
trChildren
.
forEach
((
item
,
index
)
=>
{
// if (item.keyValue) {
const
select
=
row
.
findIndex
(
v
=>
{
//
if
(
typeof
v
===
'number'
)
{
return
v
===
index
-
1
}
else
{
return
v
[
this
.
rowKey
]
===
item
.
keyValue
}
})
let
ischeck
=
item
.
checked
if
(
select
!==
-
1
)
{
if
(
typeof
selected
===
'boolean'
)
{
item
.
checked
=
selected
}
else
{
item
.
checked
=
!
item
.
checked
}
if
(
ischeck
!==
item
.
checked
)
{
this
.
check
(
item
.
rowData
||
item
,
item
.
checked
,
item
.
rowData
?
item
.
keyValue
:
null
,
true
)
}
}
// }
})
this
.
$emit
(
'selection-change'
,
{
detail
:
{
value
:
this
.
backData
,
index
:
this
.
backIndexData
}
})
},
/**
* 用于多选表格,清空用户的选择
*/
clearSelection
()
{
let
theadChildren
=
this
.
theadChildren
if
(
!
this
.
theadChildren
)
{
theadChildren
=
this
.
trChildren
[
0
]
}
// if (!this.theadChildren) return
theadChildren
.
checked
=
false
theadChildren
.
indeterminate
=
false
this
.
trChildren
.
forEach
(
item
=>
{
// if (item.keyValue) {
item
.
checked
=
false
// }
})
this
.
backData
=
[]
this
.
backIndexData
=
[]
this
.
$emit
(
'selection-change'
,
{
detail
:
{
value
:
[],
index
:
[]
}
})
},
/**
* 用于多选表格,切换所有行的选中状态
*/
toggleAllSelection
()
{
let
list
=
[]
let
startIndex
=
1
let
theadChildren
=
this
.
theadChildren
if
(
!
this
.
theadChildren
)
{
theadChildren
=
this
.
trChildren
[
0
]
}
else
{
startIndex
=
theadChildren
.
rowspan
-
1
}
this
.
trChildren
.
forEach
((
item
,
index
)
=>
{
if
(
!
item
.
disabled
)
{
if
(
index
>
(
startIndex
-
1
)
)
{
list
.
push
(
index
-
startIndex
)
}
}
})
this
.
toggleRowSelection
(
list
)
},
/**
* 选中\取消选中
* @param {Object} child
* @param {Object} check
* @param {Object} rowValue
*/
check
(
child
,
check
,
keyValue
,
emit
)
{
let
theadChildren
=
this
.
theadChildren
if
(
!
this
.
theadChildren
)
{
theadChildren
=
this
.
trChildren
[
0
]
}
let
childDomIndex
=
this
.
trChildren
.
findIndex
((
item
,
index
)
=>
child
===
item
)
if
(
childDomIndex
<
0
){
childDomIndex
=
this
.
data
.
findIndex
(
v
=>
v
[
this
.
rowKey
]
===
keyValue
)
+
1
}
const
dataLen
=
this
.
trChildren
.
filter
(
v
=>
!
v
.
disabled
&&
v
.
keyValue
).
length
if
(
childDomIndex
===
0
)
{
check
?
this
.
selectionAll
()
:
this
.
clearSelection
()
return
}
if
(
check
)
{
if
(
keyValue
)
{
this
.
backData
.
push
(
child
)
}
this
.
backIndexData
.
push
(
childDomIndex
-
1
)
}
else
{
const
index
=
this
.
backData
.
findIndex
(
v
=>
v
[
this
.
rowKey
]
===
keyValue
)
const
idx
=
this
.
backIndexData
.
findIndex
(
item
=>
item
===
childDomIndex
-
1
)
if
(
keyValue
)
{
this
.
backData
.
splice
(
index
,
1
)
}
this
.
backIndexData
.
splice
(
idx
,
1
)
}
const
domCheckAll
=
this
.
trChildren
.
find
((
item
,
index
)
=>
index
>
0
&&
!
item
.
checked
&&
!
item
.
disabled
)
if
(
!
domCheckAll
)
{
theadChildren
.
indeterminate
=
false
theadChildren
.
checked
=
true
}
else
{
theadChildren
.
indeterminate
=
true
theadChildren
.
checked
=
false
}
if
(
this
.
backIndexData
.
length
===
0
)
{
theadChildren
.
indeterminate
=
false
}
if
(
!
emit
)
{
this
.
$emit
(
'selection-change'
,
{
detail
:
{
value
:
this
.
backData
,
index
:
this
.
backIndexData
}
})
}
}
}
}
</
script
>
<
style
lang=
"scss"
>
$border-color
:
#ebeef5
;
.uni-table-scroll
{
width
:
100%
;
/* #ifndef APP-NVUE */
overflow-x
:
auto
;
/* #endif */
}
.uni-table
{
position
:
relative
;
width
:
100%
;
border-radius
:
5px
;
// box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
background-color
:
#fff
;
/* #ifndef APP-NVUE */
box-sizing
:
border-box
;
display
:
table
;
overflow-x
:
auto
;
::v-deep
.uni-table-tr
:nth-child
(
n
+
2
)
{
&
:hover
{
background-color
:
#f5f7fa
;
}
}
::v-deep
.uni-table-thead
{
.uni-table-tr
{
// background-color: #f5f7fa;
&
:hover
{
background-color
:
#fafafa
;
}
}
}
/* #endif */
}
.table--border
{
border
:
1px
$border-color
solid
;
border-right
:
none
;
}
.border-none
{
/* #ifndef APP-NVUE */
border-bottom
:
none
;
/* #endif */
}
.table--stripe
{
/* #ifndef APP-NVUE */
::v-deep
.uni-table-tr
:nth-child
(
2n
+
3
)
{
background-color
:
#fafafa
;
}
/* #endif */
}
/* 表格加载、无数据样式 */
.uni-table-loading
{
position
:
relative
;
/* #ifndef APP-NVUE */
display
:
table-row
;
/* #endif */
height
:
50px
;
line-height
:
50px
;
overflow
:
hidden
;
box-sizing
:
border-box
;
}
.empty-border
{
border-right
:
1px
$border-color
solid
;
}
.uni-table-text
{
position
:
absolute
;
right
:
0
;
left
:
0
;
text-align
:
center
;
font-size
:
14px
;
color
:
#999
;
}
.uni-table-mask
{
position
:
absolute
;
top
:
0
;
bottom
:
0
;
left
:
0
;
right
:
0
;
background-color
:
rgba
(
255
,
255
,
255
,
0
.8
);
z-index
:
99
;
/* #ifndef APP-NVUE */
display
:
flex
;
margin
:
auto
;
transition
:
all
0
.5s
;
/* #endif */
justify-content
:
center
;
align-items
:
center
;
}
.uni-table--loader
{
width
:
30px
;
height
:
30px
;
border
:
2px
solid
#aaa
;
// border-bottom-color: transparent;
border-radius
:
50%
;
/* #ifndef APP-NVUE */
animation
:
2s
uni-table--loader
linear
infinite
;
/* #endif */
position
:
relative
;
}
@keyframes
uni-table--loader
{
0
%
{
transform
:
rotate
(
360deg
);
}
10
%
{
border-left-color
:
transparent
;
}
20
%
{
border-bottom-color
:
transparent
;
}
30
%
{
border-right-color
:
transparent
;
}
40
%
{
border-top-color
:
transparent
;
}
50
%
{
transform
:
rotate
(
0deg
);
}
60
%
{
border-top-color
:
transparent
;
}
70
%
{
border-left-color
:
transparent
;
}
80
%
{
border-bottom-color
:
transparent
;
}
90
%
{
border-right-color
:
transparent
;
}
100
%
{
transform
:
rotate
(
-360deg
);
}
}
</
style
>
uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 -->
<tbody>
<slot></slot>
</tbody>
<!-- #endif -->
<!-- #ifndef H5 -->
<view><slot></slot></view>
<!-- #endif -->
</
template
>
<
script
>
export
default
{
name
:
'uniBody'
,
options
:
{
virtualHost
:
true
},
data
()
{
return
{
}
},
created
()
{},
methods
:
{}
}
</
script
>
<
style
>
</
style
>
uni_modules/uni-table/components/uni-td/uni-td.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 -->
<td
class=
"uni-table-td"
:rowspan=
"rowspan"
:colspan=
"colspan"
:class=
"
{'table--border':border}" :style="{width:width + 'px','text-align':align}">
<slot></slot>
</td>
<!-- #endif -->
<!-- #ifndef H5 -->
<!-- :class="
{'table--border':border}" -->
<view
class=
"uni-table-td"
:class=
"
{'table--border':border}" :style="{width:width + 'px','text-align':align}">
<slot></slot>
</view>
<!-- #endif -->
</
template
>
<
script
>
/**
* Td 单元格
* @description 表格中的标准单元格组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=3270
* @property {Number} align = [left|center|right] 单元格对齐方式
*/
export
default
{
name
:
'uniTd'
,
options
:
{
virtualHost
:
true
},
props
:
{
width
:
{
type
:
[
String
,
Number
],
default
:
''
},
align
:
{
type
:
String
,
default
:
'left'
},
rowspan
:
{
type
:
[
Number
,
String
],
default
:
1
},
colspan
:
{
type
:
[
Number
,
String
],
default
:
1
}
},
data
()
{
return
{
border
:
false
};
},
created
()
{
this
.
root
=
this
.
getTable
()
this
.
border
=
this
.
root
.
border
},
methods
:
{
/**
* 获取父元素实例
*/
getTable
()
{
let
parent
=
this
.
$parent
;
let
parentName
=
parent
.
$options
.
name
;
while
(
parentName
!==
'uniTable'
)
{
parent
=
parent
.
$parent
;
if
(
!
parent
)
return
false
;
parentName
=
parent
.
$options
.
name
;
}
return
parent
;
},
}
}
</
script
>
<
style
lang=
"scss"
>
$border-color
:
#EBEEF5
;
.uni-table-td
{
display
:
table-cell
;
padding
:
8px
10px
;
font-size
:
14px
;
border-bottom
:
1px
$border-color
solid
;
font-weight
:
400
;
color
:
#606266
;
line-height
:
23px
;
box-sizing
:
border-box
;
}
.table--border
{
border-right
:
1px
$border-color
solid
;
}
</
style
>
uni_modules/uni-table/components/uni-th/filter-dropdown.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"uni-filter-dropdown"
>
<view
class=
"dropdown-btn"
@
click=
"onDropdown"
>
<view
class=
"icon-select"
:class=
"
{active: canReset}" v-if="isSelect || isRange">
</view>
<view
class=
"icon-search"
:class=
"
{active: canReset}" v-if="isSearch">
<view
class=
"icon-search-0"
></view>
<view
class=
"icon-search-1"
></view>
</view>
<view
class=
"icon-calendar"
:class=
"
{active: canReset}" v-if="isDate">
<view
class=
"icon-calendar-0"
></view>
<view
class=
"icon-calendar-1"
></view>
</view>
</view>
<view
class=
"uni-dropdown-cover"
v-if=
"isOpened"
@
click=
"handleClose"
></view>
<view
class=
"dropdown-popup dropdown-popup-right"
v-if=
"isOpened"
@
click
.
stop
>
<!-- select-->
<view
v-if=
"isSelect"
class=
"list"
>
<label
class=
"flex-r a-i-c list-item"
v-for=
"(item,index) in dataList"
:key=
"index"
@
click=
"onItemClick($event, index)"
>
<check-box
class=
"check"
:checked=
"item.checked"
/>
<view
class=
"checklist-content"
>
<text
class=
"checklist-text"
:style=
"item.styleIconText"
>
{{
item
[
map
.
text
]
}}
</text>
</view>
</label>
</view>
<view
v-if=
"isSelect"
class=
"flex-r opera-area"
>
<view
class=
"flex-f btn btn-default"
:class=
"
{disable: !canReset}" @click="handleSelectReset">
{{
resource
.
reset
}}
</view>
<view
class=
"flex-f btn btn-submit"
@
click=
"handleSelectSubmit"
>
{{
resource
.
submit
}}
</view>
</view>
<!-- search -->
<view
v-if=
"isSearch"
class=
"search-area"
>
<input
class=
"search-input"
v-model=
"filterValue"
/>
</view>
<view
v-if=
"isSearch"
class=
"flex-r opera-area"
>
<view
class=
"flex-f btn btn-submit"
@
click=
"handleSearchSubmit"
>
{{
resource
.
search
}}
</view>
<view
class=
"flex-f btn btn-default"
:class=
"
{disable: !canReset}" @click="handleSearchReset">
{{
resource
.
reset
}}
</view>
</view>
<!-- range -->
<view
v-if=
"isRange"
>
<view
class=
"input-label"
>
{{
resource
.
gt
}}
</view>
<input
class=
"input"
v-model=
"gtValue"
/>
<view
class=
"input-label"
>
{{
resource
.
lt
}}
</view>
<input
class=
"input"
v-model=
"ltValue"
/>
</view>
<view
v-if=
"isRange"
class=
"flex-r opera-area"
>
<view
class=
"flex-f btn btn-default"
:class=
"
{disable: !canReset}" @click="handleRangeReset">
{{
resource
.
reset
}}
</view>
<view
class=
"flex-f btn btn-submit"
@
click=
"handleRangeSubmit"
>
{{
resource
.
submit
}}
</view>
</view>
<!-- date -->
<view
v-if=
"isDate"
>
<uni-datetime-picker
ref=
"datetimepicker"
:value=
"dateRange"
type=
"datetimerange"
return-type=
"timestamp"
@
change=
"datetimechange"
@
maskClick=
"timepickerclose"
>
<view></view>
</uni-datetime-picker>
</view>
</view>
</view>
</
template
>
<
script
>
import
checkBox
from
'../uni-tr/table-checkbox.vue'
const
resource
=
{
"reset"
:
"重置"
,
"search"
:
"搜索"
,
"submit"
:
"确定"
,
"filter"
:
"筛选"
,
"gt"
:
"大于等于"
,
"lt"
:
"小于等于"
,
"date"
:
"日期范围"
}
const
DropdownType
=
{
Select
:
"select"
,
Search
:
"search"
,
Range
:
"range"
,
Date
:
"date"
,
Timestamp
:
"timestamp"
}
export
default
{
name
:
'FilterDropdown'
,
emits
:[
'change'
],
components
:
{
checkBox
},
options
:
{
virtualHost
:
true
},
props
:
{
filterType
:
{
type
:
String
,
default
:
DropdownType
.
Select
},
filterData
:
{
type
:
Array
,
default
()
{
return
[]
}
},
mode
:
{
type
:
String
,
default
:
'default'
},
map
:
{
type
:
Object
,
default
()
{
return
{
text
:
'text'
,
value
:
'value'
}
}
}
},
computed
:
{
canReset
()
{
if
(
this
.
isSearch
)
{
return
this
.
filterValue
.
length
>
0
}
if
(
this
.
isSelect
)
{
return
this
.
checkedValues
.
length
>
0
}
if
(
this
.
isRange
)
{
return
(
this
.
gtValue
.
length
>
0
&&
this
.
ltValue
.
length
>
0
)
}
if
(
this
.
isDate
)
{
return
this
.
dateSelect
.
length
>
0
}
return
false
},
isSelect
()
{
return
this
.
filterType
===
DropdownType
.
Select
},
isSearch
()
{
return
this
.
filterType
===
DropdownType
.
Search
},
isRange
()
{
return
this
.
filterType
===
DropdownType
.
Range
},
isDate
()
{
return
(
this
.
filterType
===
DropdownType
.
Date
||
this
.
filterType
===
DropdownType
.
Timestamp
)
}
},
watch
:
{
filterData
(
newVal
)
{
this
.
_copyFilters
()
},
indeterminate
(
newVal
)
{
this
.
isIndeterminate
=
newVal
}
},
data
()
{
return
{
resource
,
enabled
:
true
,
isOpened
:
false
,
dataList
:
[],
filterValue
:
''
,
checkedValues
:
[],
gtValue
:
''
,
ltValue
:
''
,
dateRange
:
[],
dateSelect
:
[]
};
},
created
()
{
this
.
_copyFilters
()
},
methods
:
{
_copyFilters
()
{
let
dl
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
filterData
))
for
(
let
i
=
0
;
i
<
dl
.
length
;
i
++
)
{
if
(
dl
[
i
].
checked
===
undefined
)
{
dl
[
i
].
checked
=
false
}
}
this
.
dataList
=
dl
},
openPopup
()
{
this
.
isOpened
=
true
if
(
this
.
isDate
)
{
this
.
$nextTick
(()
=>
{
if
(
!
this
.
dateRange
.
length
)
{
this
.
resetDate
()
}
this
.
$refs
.
datetimepicker
.
show
()
})
}
},
closePopup
()
{
this
.
isOpened
=
false
},
handleClose
(
e
)
{
this
.
closePopup
()
},
resetDate
()
{
let
date
=
new
Date
()
let
dateText
=
date
.
toISOString
().
split
(
'T'
)[
0
]
this
.
dateRange
=
[
dateText
+
' 0:00:00'
,
dateText
+
' 23:59:59'
]
},
onDropdown
(
e
)
{
this
.
openPopup
()
},
onItemClick
(
e
,
index
)
{
let
items
=
this
.
dataList
let
listItem
=
items
[
index
]
if
(
listItem
.
checked
===
undefined
)
{
items
[
index
].
checked
=
true
}
else
{
items
[
index
].
checked
=
!
listItem
.
checked
}
let
checkvalues
=
[]
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
const
item
=
items
[
i
]
if
(
item
.
checked
)
{
checkvalues
.
push
(
item
.
value
)
}
}
this
.
checkedValues
=
checkvalues
},
datetimechange
(
e
)
{
this
.
closePopup
()
this
.
dateRange
=
e
this
.
dateSelect
=
e
this
.
$emit
(
'change'
,
{
filterType
:
this
.
filterType
,
filter
:
e
})
},
timepickerclose
(
e
)
{
this
.
closePopup
()
},
handleSelectSubmit
()
{
this
.
closePopup
()
this
.
$emit
(
'change'
,
{
filterType
:
this
.
filterType
,
filter
:
this
.
checkedValues
})
},
handleSelectReset
()
{
if
(
!
this
.
canReset
)
{
return
;
}
var
items
=
this
.
dataList
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
let
item
=
items
[
i
]
this
.
$set
(
item
,
'checked'
,
false
)
}
this
.
checkedValues
=
[]
this
.
handleSelectSubmit
()
},
handleSearchSubmit
()
{
this
.
closePopup
()
this
.
$emit
(
'change'
,
{
filterType
:
this
.
filterType
,
filter
:
this
.
filterValue
})
},
handleSearchReset
()
{
if
(
!
this
.
canReset
)
{
return
;
}
this
.
filterValue
=
''
this
.
handleSearchSubmit
()
},
handleRangeSubmit
(
isReset
)
{
this
.
closePopup
()
this
.
$emit
(
'change'
,
{
filterType
:
this
.
filterType
,
filter
:
isReset
===
true
?
[]
:
[
parseInt
(
this
.
gtValue
),
parseInt
(
this
.
ltValue
)]
})
},
handleRangeReset
()
{
if
(
!
this
.
canReset
)
{
return
;
}
this
.
gtValue
=
''
this
.
ltValue
=
''
this
.
handleRangeSubmit
(
true
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.flex-r
{
display
:
flex
;
flex-direction
:
row
;
}
.flex-f
{
flex
:
1
;
}
.a-i-c
{
align-items
:
center
;
}
.j-c-c
{
justify-content
:
center
;
}
.icon-select
{
width
:
14px
;
height
:
16px
;
border
:
solid
6px
transparent
;
border-top
:
solid
6px
#ddd
;
border-bottom
:
none
;
background-color
:
#ddd
;
background-clip
:
content-box
;
box-sizing
:
border-box
;
}
.icon-select.active
{
background-color
:
#1890ff
;
border-top-color
:
#1890ff
;
}
.icon-search
{
width
:
12px
;
height
:
16px
;
position
:
relative
;
}
.icon-search-0
{
border
:
2px
solid
#ddd
;
border-radius
:
8px
;
width
:
7px
;
height
:
7px
;
}
.icon-search-1
{
position
:
absolute
;
top
:
8px
;
right
:
0
;
width
:
1px
;
height
:
7px
;
background-color
:
#ddd
;
transform
:
rotate
(
-45deg
);
}
.icon-search.active
.icon-search-0
{
border-color
:
#1890ff
;
}
.icon-search.active
.icon-search-1
{
background-color
:
#1890ff
;
}
.icon-calendar
{
color
:
#ddd
;
width
:
14px
;
height
:
16px
;
}
.icon-calendar-0
{
height
:
4px
;
margin-top
:
3px
;
margin-bottom
:
1px
;
background-color
:
#ddd
;
border-radius
:
2px
2px
1px
1px
;
position
:
relative
;
}
.icon-calendar-0
:before
,
.icon-calendar-0
:after
{
content
:
''
;
position
:
absolute
;
top
:
-3px
;
width
:
4px
;
height
:
3px
;
border-radius
:
1px
;
background-color
:
#ddd
;
}
.icon-calendar-0
:before
{
left
:
2px
;
}
.icon-calendar-0
:after
{
right
:
2px
;
}
.icon-calendar-1
{
height
:
9px
;
background-color
:
#ddd
;
border-radius
:
1px
1px
2px
2px
;
}
.icon-calendar.active
{
color
:
#1890ff
;
}
.icon-calendar.active
.icon-calendar-0
,
.icon-calendar.active
.icon-calendar-1
,
.icon-calendar.active
.icon-calendar-0
:before
,
.icon-calendar.active
.icon-calendar-0
:after
{
background-color
:
#1890ff
;
}
.uni-filter-dropdown
{
position
:
relative
;
font-weight
:
normal
;
}
.dropdown-popup
{
position
:
absolute
;
top
:
100%
;
background-color
:
#fff
;
box-shadow
:
0
3px
6px
-4px
#000000
1f
,
0
6px
16px
#000000
14
,
0
9px
28px
8px
#000000
0d
;
min-width
:
150px
;
z-index
:
1000
;
}
.dropdown-popup-left
{
left
:
0
;
}
.dropdown-popup-right
{
right
:
0
;
}
.uni-dropdown-cover
{
position
:
fixed
;
left
:
0
;
top
:
0
;
right
:
0
;
bottom
:
0
;
background-color
:
transparent
;
z-index
:
100
;
}
.list
{
margin-top
:
5px
;
margin-bottom
:
5px
;
}
.list-item
{
padding
:
5px
10px
;
text-align
:
left
;
}
.list-item
:hover
{
background-color
:
#f0f0f0
;
}
.check
{
margin-right
:
5px
;
}
.search-area
{
padding
:
10px
;
}
.search-input
{
font-size
:
12px
;
border
:
1px
solid
#f0f0f0
;
border-radius
:
3px
;
padding
:
2px
5px
;
min-width
:
150px
;
text-align
:
left
;
}
.input-label
{
margin
:
10px
10px
5px
10px
;
text-align
:
left
;
}
.input
{
font-size
:
12px
;
border
:
1px
solid
#f0f0f0
;
border-radius
:
3px
;
margin
:
10px
;
padding
:
2px
5px
;
min-width
:
150px
;
text-align
:
left
;
}
.opera-area
{
cursor
:
default
;
border-top
:
1px
solid
#ddd
;
padding
:
5px
;
}
.opera-area
.btn
{
font-size
:
12px
;
border-radius
:
3px
;
margin
:
5px
;
padding
:
4px
4px
;
}
.btn-default
{
border
:
1px
solid
#ddd
;
}
.btn-default.disable
{
border-color
:
transparent
;
}
.btn-submit
{
background-color
:
#1890ff
;
color
:
#ffffff
;
}
</
style
>
uni_modules/uni-table/components/uni-th/uni-th.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 -->
<th
:rowspan=
"rowspan"
:colspan=
"colspan"
class=
"uni-table-th"
:class=
"
{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }">
<view
class=
"uni-table-th-row"
>
<view
class=
"uni-table-th-content"
:style=
"
{ 'justify-content': contentAlign }" @click="sort">
<slot></slot>
<view
v-if=
"sortable"
class=
"arrow-box"
>
<text
class=
"arrow up"
:class=
"
{ active: ascending }" @click.stop="ascendingFn">
</text>
<text
class=
"arrow down"
:class=
"
{ active: descending }" @click.stop="descendingFn">
</text>
</view>
</view>
<dropdown
v-if=
"filterType || filterData.length"
:filterData=
"filterData"
:filterType=
"filterType"
@
change=
"ondropdown"
></dropdown>
</view>
</th>
<!-- #endif -->
<!-- #ifndef H5 -->
<view
class=
"uni-table-th"
:class=
"
{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }">
<slot></slot></view>
<!-- #endif -->
</
template
>
<
script
>
// #ifdef H5
import
dropdown
from
'./filter-dropdown.vue'
// #endif
/**
* Th 表头
* @description 表格内的表头单元格组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=3270
* @property {Number | String} width 单元格宽度(支持纯数字、携带单位px或rpx)
* @property {Boolean} sortable 是否启用排序
* @property {Number} align = [left|center|right] 单元格对齐方式
* @value left 单元格文字左侧对齐
* @value center 单元格文字居中
* @value right 单元格文字右侧对齐
* @property {Array} filterData 筛选数据
* @property {String} filterType [search|select] 筛选类型
* @value search 关键字搜素
* @value select 条件选择
* @event {Function} sort-change 排序触发事件
*/
export
default
{
name
:
'uniTh'
,
options
:
{
virtualHost
:
true
},
components
:
{
// #ifdef H5
dropdown
// #endif
},
emits
:[
'sort-change'
,
'filter-change'
],
props
:
{
width
:
{
type
:
[
String
,
Number
],
default
:
''
},
align
:
{
type
:
String
,
default
:
'left'
},
rowspan
:
{
type
:
[
Number
,
String
],
default
:
1
},
colspan
:
{
type
:
[
Number
,
String
],
default
:
1
},
sortable
:
{
type
:
Boolean
,
default
:
false
},
filterType
:
{
type
:
String
,
default
:
""
},
filterData
:
{
type
:
Array
,
default
()
{
return
[]
}
}
},
data
()
{
return
{
border
:
false
,
ascending
:
false
,
descending
:
false
}
},
computed
:
{
// 根据props中的width属性 自动匹配当前th的宽度(px)
customWidth
(){
if
(
typeof
this
.
width
===
'number'
){
return
this
.
width
}
else
if
(
typeof
this
.
width
===
'string'
)
{
let
regexHaveUnitPx
=
new
RegExp
(
/^
[
1-9
][
0-9
]
*px$/g
)
let
regexHaveUnitRpx
=
new
RegExp
(
/^
[
1-9
][
0-9
]
*rpx$/g
)
let
regexHaveNotUnit
=
new
RegExp
(
/^
[
1-9
][
0-9
]
*$/g
)
if
(
this
.
width
.
match
(
regexHaveUnitPx
)
!==
null
)
{
// 携带了 px
return
this
.
width
.
replace
(
'px'
,
''
)
}
else
if
(
this
.
width
.
match
(
regexHaveUnitRpx
)
!==
null
)
{
// 携带了 rpx
let
numberRpx
=
Number
(
this
.
width
.
replace
(
'rpx'
,
''
))
let
widthCoe
=
uni
.
getSystemInfoSync
().
screenWidth
/
750
return
Math
.
round
(
numberRpx
*
widthCoe
)
}
else
if
(
this
.
width
.
match
(
regexHaveNotUnit
)
!==
null
)
{
// 未携带 rpx或px 的纯数字 String
return
this
.
width
}
else
{
// 不符合格式
return
''
}
}
else
{
return
''
}
},
contentAlign
()
{
let
align
=
'left'
switch
(
this
.
align
)
{
case
'left'
:
align
=
'flex-start'
break
case
'center'
:
align
=
'center'
break
case
'right'
:
align
=
'flex-end'
break
}
return
align
}
},
created
()
{
this
.
root
=
this
.
getTable
(
'uniTable'
)
this
.
rootTr
=
this
.
getTable
(
'uniTr'
)
this
.
rootTr
.
minWidthUpdate
(
this
.
customWidth
?
this
.
customWidth
:
140
)
this
.
border
=
this
.
root
.
border
this
.
root
.
thChildren
.
push
(
this
)
},
methods
:
{
sort
()
{
if
(
!
this
.
sortable
)
return
this
.
clearOther
()
if
(
!
this
.
ascending
&&
!
this
.
descending
)
{
this
.
ascending
=
true
this
.
$emit
(
'sort-change'
,
{
order
:
'ascending'
})
return
}
if
(
this
.
ascending
&&
!
this
.
descending
)
{
this
.
ascending
=
false
this
.
descending
=
true
this
.
$emit
(
'sort-change'
,
{
order
:
'descending'
})
return
}
if
(
!
this
.
ascending
&&
this
.
descending
)
{
this
.
ascending
=
false
this
.
descending
=
false
this
.
$emit
(
'sort-change'
,
{
order
:
null
})
}
},
ascendingFn
()
{
this
.
clearOther
()
this
.
ascending
=
!
this
.
ascending
this
.
descending
=
false
this
.
$emit
(
'sort-change'
,
{
order
:
this
.
ascending
?
'ascending'
:
null
})
},
descendingFn
()
{
this
.
clearOther
()
this
.
descending
=
!
this
.
descending
this
.
ascending
=
false
this
.
$emit
(
'sort-change'
,
{
order
:
this
.
descending
?
'descending'
:
null
})
},
clearOther
()
{
this
.
root
.
thChildren
.
map
(
item
=>
{
if
(
item
!==
this
)
{
item
.
ascending
=
false
item
.
descending
=
false
}
return
item
})
},
ondropdown
(
e
)
{
this
.
$emit
(
"filter-change"
,
e
)
},
/**
* 获取父元素实例
*/
getTable
(
name
)
{
let
parent
=
this
.
$parent
let
parentName
=
parent
.
$options
.
name
while
(
parentName
!==
name
)
{
parent
=
parent
.
$parent
if
(
!
parent
)
return
false
parentName
=
parent
.
$options
.
name
}
return
parent
}
}
}
</
script
>
<
style
lang=
"scss"
>
$border-color
:
#ebeef5
;
.uni-table-th
{
padding
:
12px
10px
;
/* #ifndef APP-NVUE */
display
:
table-cell
;
box-sizing
:
border-box
;
/* #endif */
font-size
:
14px
;
font-weight
:
bold
;
color
:
#909399
;
border-bottom
:
1px
$border-color
solid
;
}
.uni-table-th-row
{
/* #ifndef APP-NVUE */
display
:
flex
;
/* #endif */
flex-direction
:
row
;
}
.table--border
{
border-right
:
1px
$border-color
solid
;
}
.uni-table-th-content
{
display
:
flex
;
align-items
:
center
;
flex
:
1
;
}
.arrow-box
{
}
.arrow
{
display
:
block
;
position
:
relative
;
width
:
10px
;
height
:
8px
;
// border: 1px red solid;
left
:
5px
;
overflow
:
hidden
;
cursor
:
pointer
;
}
.down
{
top
:
3px
;
::after
{
content
:
''
;
width
:
8px
;
height
:
8px
;
position
:
absolute
;
left
:
2px
;
top
:
-5px
;
transform
:
rotate
(
45deg
);
background-color
:
#ccc
;
}
&
.active
{
::after
{
background-color
:
#007aff
;
}
}
}
.up
{
::after
{
content
:
''
;
width
:
8px
;
height
:
8px
;
position
:
absolute
;
left
:
2px
;
top
:
5px
;
transform
:
rotate
(
45deg
);
background-color
:
#ccc
;
}
&
.active
{
::after
{
background-color
:
#007aff
;
}
}
}
</
style
>
uni_modules/uni-table/components/uni-thead/uni-thead.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 -->
<thead
class=
"uni-table-thead"
>
<tr
class=
"uni-table-tr"
>
<th
:rowspan=
"rowspan"
colspan=
"1"
class=
"checkbox"
:class=
"
{ 'tr-table--border': border }">
<table-checkbox
:indeterminate=
"indeterminate"
:checked=
"checked"
@
checkboxSelected=
"checkboxSelected"
></table-checkbox>
</th>
</tr>
<slot></slot>
</thead>
<!-- #endif -->
<!-- #ifndef H5 -->
<view
class=
"uni-table-thead"
><slot></slot></view>
<!-- #endif -->
</
template
>
<
script
>
import
tableCheckbox
from
'../uni-tr/table-checkbox.vue'
export
default
{
name
:
'uniThead'
,
components
:
{
tableCheckbox
},
options
:
{
virtualHost
:
true
},
data
()
{
return
{
border
:
false
,
selection
:
false
,
rowspan
:
1
,
indeterminate
:
false
,
checked
:
false
}
},
created
()
{
this
.
root
=
this
.
getTable
()
// #ifdef H5
this
.
root
.
theadChildren
=
this
// #endif
this
.
border
=
this
.
root
.
border
this
.
selection
=
this
.
root
.
type
},
methods
:
{
init
(
self
)
{
this
.
rowspan
++
},
checkboxSelected
(
e
)
{
this
.
indeterminate
=
false
const
backIndexData
=
this
.
root
.
backIndexData
const
data
=
this
.
root
.
trChildren
.
filter
(
v
=>
!
v
.
disabled
&&
v
.
keyValue
)
if
(
backIndexData
.
length
===
data
.
length
)
{
this
.
checked
=
false
this
.
root
.
clearSelection
()
}
else
{
this
.
checked
=
true
this
.
root
.
selectionAll
()
}
},
/**
* 获取父元素实例
*/
getTable
(
name
=
'uniTable'
)
{
let
parent
=
this
.
$parent
let
parentName
=
parent
.
$options
.
name
while
(
parentName
!==
name
)
{
parent
=
parent
.
$parent
if
(
!
parent
)
return
false
parentName
=
parent
.
$options
.
name
}
return
parent
}
}
}
</
script
>
<
style
lang=
"scss"
>
$border-color
:
#ebeef5
;
.uni-table-thead
{
display
:
table-header-group
;
}
.uni-table-tr
{
/* #ifndef APP-NVUE */
display
:
table-row
;
transition
:
all
0
.3s
;
box-sizing
:
border-box
;
/* #endif */
border
:
1px
red
solid
;
background-color
:
#fafafa
;
}
.checkbox
{
padding
:
0
8px
;
width
:
26px
;
padding-left
:
12px
;
/* #ifndef APP-NVUE */
display
:
table-cell
;
vertical-align
:
middle
;
/* #endif */
color
:
#333
;
font-weight
:
500
;
border-bottom
:
1px
$border-color
solid
;
font-size
:
14px
;
// text-align: center;
}
.tr-table--border
{
border-right
:
1px
$border-color
solid
;
}
/* #ifndef APP-NVUE */
.uni-table-tr
{
::v-deep
.uni-table-th
{
&
.table--border
:last-child
{
// border-right: none;
}
}
::v-deep
.uni-table-td
{
&
.table--border
:last-child
{
// border-right: none;
}
}
}
/* #endif */
</
style
>
uni_modules/uni-table/components/uni-tr/table-checkbox.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"uni-table-checkbox"
@
click=
"selected"
>
<view
v-if=
"!indeterminate"
class=
"checkbox__inner"
:class=
"
{'is-checked':isChecked,'is-disable':isDisabled}">
<view
class=
"checkbox__inner-icon"
></view>
</view>
<view
v-else
class=
"checkbox__inner checkbox--indeterminate"
>
<view
class=
"checkbox__inner-icon"
></view>
</view>
</view>
</
template
>
<
script
>
export
default
{
name
:
'TableCheckbox'
,
emits
:[
'checkboxSelected'
],
props
:
{
indeterminate
:
{
type
:
Boolean
,
default
:
false
},
checked
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
disabled
:
{
type
:
Boolean
,
default
:
false
},
index
:
{
type
:
Number
,
default
:
-
1
},
cellData
:
{
type
:
Object
,
default
()
{
return
{}
}
}
},
watch
:{
checked
(
newVal
){
if
(
typeof
this
.
checked
===
'boolean'
){
this
.
isChecked
=
newVal
}
else
{
this
.
isChecked
=
true
}
},
indeterminate
(
newVal
){
this
.
isIndeterminate
=
newVal
}
},
data
()
{
return
{
isChecked
:
false
,
isDisabled
:
false
,
isIndeterminate
:
false
}
},
created
()
{
if
(
typeof
this
.
checked
===
'boolean'
){
this
.
isChecked
=
this
.
checked
}
this
.
isDisabled
=
this
.
disabled
},
methods
:
{
selected
()
{
if
(
this
.
isDisabled
)
return
this
.
isIndeterminate
=
false
this
.
isChecked
=
!
this
.
isChecked
this
.
$emit
(
'checkboxSelected'
,
{
checked
:
this
.
isChecked
,
data
:
this
.
cellData
})
}
}
}
</
script
>
<
style
lang=
"scss"
>
$checked-color
:
#007aff
;
$border-color
:
#DCDFE6
;
$disable
:
0
.4
;
.uni-table-checkbox
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
center
;
position
:
relative
;
margin
:
5px
0
;
cursor
:
pointer
;
// 多选样式
.checkbox__inner
{
/* #ifndef APP-NVUE */
flex-shrink
:
0
;
box-sizing
:
border-box
;
/* #endif */
position
:
relative
;
width
:
16px
;
height
:
16px
;
border
:
1px
solid
$border-color
;
border-radius
:
2px
;
background-color
:
#fff
;
z-index
:
1
;
.checkbox__inner-icon
{
position
:
absolute
;
/* #ifdef APP-NVUE */
top
:
2px
;
/* #endif */
/* #ifndef APP-NVUE */
top
:
2px
;
/* #endif */
left
:
5px
;
height
:
7px
;
width
:
3px
;
border
:
1px
solid
#fff
;
border-left
:
0
;
border-top
:
0
;
opacity
:
0
;
transform-origin
:
center
;
transform
:
rotate
(
45deg
);
box-sizing
:
content-box
;
}
&
.checkbox--indeterminate
{
border-color
:
$checked-color
;
background-color
:
$checked-color
;
.checkbox__inner-icon
{
position
:
absolute
;
opacity
:
1
;
transform
:
rotate
(
0deg
);
height
:
2px
;
top
:
0
;
bottom
:
0
;
margin
:
auto
;
left
:
0px
;
right
:
0px
;
bottom
:
0
;
width
:
auto
;
border
:
none
;
border-radius
:
2px
;
transform
:
scale
(
0
.5
);
background-color
:
#fff
;
}
}
&
:hover
{
border-color
:
$checked-color
;
}
// 禁用
&
.is-disable
{
/* #ifdef H5 */
cursor
:
not
-
allowed
;
/* #endif */
background-color
:
#F2F6FC
;
border-color
:
$border-color
;
}
// 选中
&
.is-checked
{
border-color
:
$checked-color
;
background-color
:
$checked-color
;
.checkbox__inner-icon
{
opacity
:
1
;
transform
:
rotate
(
45deg
);
}
// 选中禁用
&
.is-disable
{
opacity
:
$disable
;
}
}
}
}
</
style
>
uni_modules/uni-table/components/uni-tr/uni-tr.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 -->
<tr
class=
"uni-table-tr"
>
<th
v-if=
"selection === 'selection' && ishead"
class=
"checkbox"
:class=
"
{ 'tr-table--border': border }">
<table-checkbox
:checked=
"checked"
:indeterminate=
"indeterminate"
:disabled=
"disabled"
@
checkboxSelected=
"checkboxSelected"
></table-checkbox>
</th>
<slot></slot>
<!--
<uni-th
class=
"th-fixed"
>
123
</uni-th>
-->
</tr>
<!-- #endif -->
<!-- #ifndef H5 -->
<view
class=
"uni-table-tr"
>
<view
v-if=
"selection === 'selection' "
class=
"checkbox"
:class=
"
{ 'tr-table--border': border }">
<table-checkbox
:checked=
"checked"
:indeterminate=
"indeterminate"
:disabled=
"disabled"
@
checkboxSelected=
"checkboxSelected"
></table-checkbox>
</view>
<slot></slot>
</view>
<!-- #endif -->
</
template
>
<
script
>
import
tableCheckbox
from
'./table-checkbox.vue'
/**
* Tr 表格行组件
* @description 表格行组件 仅包含 th,td 组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=
*/
export
default
{
name
:
'uniTr'
,
components
:
{
tableCheckbox
},
props
:
{
disabled
:
{
type
:
Boolean
,
default
:
false
},
keyValue
:
{
type
:
[
String
,
Number
],
default
:
''
}
},
options
:
{
virtualHost
:
true
},
data
()
{
return
{
value
:
false
,
border
:
false
,
selection
:
false
,
widthThArr
:
[],
ishead
:
true
,
checked
:
false
,
indeterminate
:
false
}
},
created
()
{
this
.
root
=
this
.
getTable
()
this
.
head
=
this
.
getTable
(
'uniThead'
)
if
(
this
.
head
)
{
this
.
ishead
=
false
this
.
head
.
init
(
this
)
}
this
.
border
=
this
.
root
.
border
this
.
selection
=
this
.
root
.
type
this
.
root
.
trChildren
.
push
(
this
)
const
rowData
=
this
.
root
.
data
.
find
(
v
=>
v
[
this
.
root
.
rowKey
]
===
this
.
keyValue
)
if
(
rowData
){
this
.
rowData
=
rowData
}
this
.
root
.
isNodata
()
},
mounted
()
{
if
(
this
.
widthThArr
.
length
>
0
)
{
const
selectionWidth
=
this
.
selection
===
'selection'
?
50
:
0
this
.
root
.
minWidth
=
this
.
widthThArr
.
reduce
((
a
,
b
)
=>
Number
(
a
)
+
Number
(
b
))
+
selectionWidth
}
},
// #ifndef VUE3
destroyed
()
{
const
index
=
this
.
root
.
trChildren
.
findIndex
(
i
=>
i
===
this
)
this
.
root
.
trChildren
.
splice
(
index
,
1
)
this
.
root
.
isNodata
()
},
// #endif
// #ifdef VUE3
unmounted
()
{
const
index
=
this
.
root
.
trChildren
.
findIndex
(
i
=>
i
===
this
)
this
.
root
.
trChildren
.
splice
(
index
,
1
)
this
.
root
.
isNodata
()
},
// #endif
methods
:
{
minWidthUpdate
(
width
)
{
this
.
widthThArr
.
push
(
width
)
},
// 选中
checkboxSelected
(
e
)
{
let
rootData
=
this
.
root
.
data
.
find
(
v
=>
v
[
this
.
root
.
rowKey
]
===
this
.
keyValue
)
this
.
checked
=
e
.
checked
this
.
root
.
check
(
rootData
||
this
,
e
.
checked
,
rootData
?
this
.
keyValue
:
null
)
},
change
(
e
)
{
this
.
root
.
trChildren
.
forEach
(
item
=>
{
if
(
item
===
this
)
{
this
.
root
.
check
(
this
,
e
.
detail
.
value
.
length
>
0
?
true
:
false
)
}
})
},
/**
* 获取父元素实例
*/
getTable
(
name
=
'uniTable'
)
{
let
parent
=
this
.
$parent
let
parentName
=
parent
.
$options
.
name
while
(
parentName
!==
name
)
{
parent
=
parent
.
$parent
if
(
!
parent
)
return
false
parentName
=
parent
.
$options
.
name
}
return
parent
}
}
}
</
script
>
<
style
lang=
"scss"
>
$border-color
:
#ebeef5
;
.uni-table-tr
{
/* #ifndef APP-NVUE */
display
:
table-row
;
transition
:
all
0
.3s
;
box-sizing
:
border-box
;
/* #endif */
}
.checkbox
{
padding
:
0
8px
;
width
:
26px
;
padding-left
:
12px
;
/* #ifndef APP-NVUE */
display
:
table-cell
;
vertical-align
:
middle
;
/* #endif */
color
:
#333
;
font-weight
:
500
;
border-bottom
:
1px
$border-color
solid
;
font-size
:
14px
;
// text-align: center;
}
.tr-table--border
{
border-right
:
1px
$border-color
solid
;
}
/* #ifndef APP-NVUE */
.uni-table-tr
{
::v-deep
.uni-table-th
{
&
.table--border
:last-child
{
// border-right: none;
}
}
::v-deep
.uni-table-td
{
&
.table--border
:last-child
{
// border-right: none;
}
}
}
/* #endif */
</
style
>
uni_modules/uni-table/i18n/en.json
0 → 100644
View file @
dcd21c31
{
"filter-dropdown.reset"
:
"Reset"
,
"filter-dropdown.search"
:
"Search"
,
"filter-dropdown.submit"
:
"Submit"
,
"filter-dropdown.filter"
:
"Filter"
,
"filter-dropdown.gt"
:
"Greater or equal to"
,
"filter-dropdown.lt"
:
"Less than or equal to"
,
"filter-dropdown.date"
:
"Date"
}
uni_modules/uni-table/i18n/es.json
0 → 100644
View file @
dcd21c31
{
"filter-dropdown.reset"
:
"Reiniciar"
,
"filter-dropdown.search"
:
"Búsqueda"
,
"filter-dropdown.submit"
:
"Entregar"
,
"filter-dropdown.filter"
:
"Filtrar"
,
"filter-dropdown.gt"
:
"Mayor o igual a"
,
"filter-dropdown.lt"
:
"Menos que o igual a"
,
"filter-dropdown.date"
:
"Fecha"
}
uni_modules/uni-table/i18n/fr.json
0 → 100644
View file @
dcd21c31
{
"filter-dropdown.reset"
:
"Réinitialiser"
,
"filter-dropdown.search"
:
"Chercher"
,
"filter-dropdown.submit"
:
"Soumettre"
,
"filter-dropdown.filter"
:
"Filtre"
,
"filter-dropdown.gt"
:
"Supérieur ou égal à"
,
"filter-dropdown.lt"
:
"Inférieur ou égal à"
,
"filter-dropdown.date"
:
"Date"
}
uni_modules/uni-table/i18n/index.js
0 → 100644
View file @
dcd21c31
import
en
from
'./en.json'
import
es
from
'./es.json'
import
fr
from
'./fr.json'
import
zhHans
from
'./zh-Hans.json'
import
zhHant
from
'./zh-Hant.json'
export
default
{
en
,
es
,
fr
,
'zh-Hans'
:
zhHans
,
'zh-Hant'
:
zhHant
}
uni_modules/uni-table/i18n/zh-Hans.json
0 → 100644
View file @
dcd21c31
{
"filter-dropdown.reset"
:
"重置"
,
"filter-dropdown.search"
:
"搜索"
,
"filter-dropdown.submit"
:
"确定"
,
"filter-dropdown.filter"
:
"筛选"
,
"filter-dropdown.gt"
:
"大于等于"
,
"filter-dropdown.lt"
:
"小于等于"
,
"filter-dropdown.date"
:
"日期范围"
}
uni_modules/uni-table/i18n/zh-Hant.json
0 → 100644
View file @
dcd21c31
{
"filter-dropdown.reset"
:
"重置"
,
"filter-dropdown.search"
:
"搜索"
,
"filter-dropdown.submit"
:
"確定"
,
"filter-dropdown.filter"
:
"篩選"
,
"filter-dropdown.gt"
:
"大於等於"
,
"filter-dropdown.lt"
:
"小於等於"
,
"filter-dropdown.date"
:
"日期範圍"
}
uni_modules/uni-table/package.json
0 → 100644
View file @
dcd21c31
{
"id"
:
"uni-table"
,
"displayName"
:
"uni-table 表格"
,
"version"
:
"1.2.1"
,
"description"
:
"表格组件,多用于展示多条结构类似的数据,如"
,
"keywords"
:
[
"uni-ui"
,
"uniui"
,
"table"
,
"表格"
],
"repository"
:
"https://github.com/dcloudio/uni-ui"
,
"engines"
:
{
"HBuilderX"
:
""
},
"directories"
:
{
"example"
:
"../../temps/example_temps"
},
"dcloudext"
:
{
"category"
:
[
"前端组件"
,
"通用组件"
],
"sale"
:
{
"regular"
:
{
"price"
:
"0.00"
},
"sourcecode"
:
{
"price"
:
"0.00"
}
},
"contact"
:
{
"qq"
:
""
},
"declaration"
:
{
"ads"
:
"无"
,
"data"
:
"无"
,
"permissions"
:
"无"
},
"npmurl"
:
"https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules"
:
{
"dependencies"
:
[
"uni-scss"
,
"uni-datetime-picker"
],
"encrypt"
:
[],
"platforms"
:
{
"cloud"
:
{
"tcb"
:
"y"
,
"aliyun"
:
"y"
},
"client"
:
{
"App"
:
{
"app-vue"
:
"y"
,
"app-nvue"
:
"n"
},
"H5-mobile"
:
{
"Safari"
:
"y"
,
"Android Browser"
:
"y"
,
"微信浏览器(Android)"
:
"y"
,
"QQ浏览器(Android)"
:
"y"
},
"H5-pc"
:
{
"Chrome"
:
"y"
,
"IE"
:
"y"
,
"Edge"
:
"y"
,
"Firefox"
:
"y"
,
"Safari"
:
"y"
},
"小程序"
:
{
"微信"
:
"y"
,
"阿里"
:
"y"
,
"百度"
:
"y"
,
"字节跳动"
:
"n"
,
"QQ"
:
"y"
},
"快应用"
:
{
"华为"
:
"n"
,
"联盟"
:
"n"
},
"Vue"
:
{
"vue2"
:
"y"
,
"vue3"
:
"y"
}
}
}
}
}
\ No newline at end of file
uni_modules/uni-table/readme.md
0 → 100644
View file @
dcd21c31
## Table 表单
> 组件名:``uni-table``,代码块: `uTable`。
用于展示多条结构类似的数据
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-table)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
uni_modules/zb-table/changelog.md
0 → 100644
View file @
dcd21c31
## 1.2.18(2023-06-01)
更新
## 1.2.16(2023-05-10)
增加单元格点击事件
完善文档
增加示例
## 1.2.15(2022-08-25)
优化部分细节
## 1.2.14(2022-04-25)
修改vue 3 报错小程序Generated an empty chunk: "uni_modules/zb-table/components/zb-table/js/util"
## 1.2.13(2022-04-22)
增加图片宽度设置
## 1.2.12(2022-04-22)
修复pc端 滚动条占位问题
## 1.2.11(2022-04-22)
增加多图片展示
## 1.2.10(2022-04-19)
版本解决冲突
## 1.2.9(2022-04-19)
暂时去掉多级表头...有着某些问题,正在修复中
## 1.1.9(2022-04-19)
暂时去掉多级表头...有着某些问题,正在修复中
## 1.1.23(2022-04-19)
暂时去掉多级表头,有着某些问题,修复中。。。
## 1.1.22(2022-04-19)
暂时去掉多级表头,存在某些问题 ,正在修复中
## 1.1.21(2022-03-29)
优化数字问题
## 1.1.20(2022-03-29)
优化按钮,可以自定义按钮,自定义添加class
## 1.1.19(2022-03-28)
进行优化加载
## 1.1.18(2022-03-28)
修复pc端滚动条问题
## 1.1.17(2022-03-25)
修改 数据回显的时候,全选框没有选中效果
## 1.1.16(2022-03-25)
新增:table属性 cell-style 修改单元格样式
## 1.1.15(2022-03-23)
fix:支付宝小程序上拉加载e.detail 没有值导致上拉加载失效 ,已修复
## 1.1.14(2022-03-23)
fix: 支付宝小程序左右无法滑动的问题
## 1.1.13(2022-03-21)
fix:英文宽度自适应问题
## 1.1.12(2022-03-20)
修改自适应宽度问题
## 1.1.11(2022-03-19)
增加上拉加载功能
## 1.1.10(2022-03-18)
修改合计不更新问题
## 1.1.9(2022-03-16)
优化css 样式
## 1.1.8(2022-03-16)
增加表尾合计行
## 1.1.7(2022-03-15)
修改css样式
## 1.1.6(2022-03-14)
进行代码优化
## 1.1.5(2022-03-12)
更新一个操作按钮的时候 报错问题,进行代码优化
## 1.1.4(2022-03-12)
增加图片统一高度
## 1.1.3(2022-03-12)
增加图片地址 ,并且图片支持预览功能
## 1.1.2(2022-03-11)
新增默认 是否选中功能,进行优化
## 1.1.1(2022-03-10)
新增单击事件
## 1.1.0(2022-03-10)
-
增加单击事件
## 1.1.0(2022-03-10)
-
增加checkbox功能 ,进行优化
## 1.0.11(2022-03-09)
-
修改小程序中排序问题
## 1.0.10(2022-03-09)
-
做了兼容性处理
## 1.0.8(2022-03-09)
-
进行优化滚动防止 多次计算
## 1.0.7(2022-03-09)
-
修改一些问题 新增过滤器
## 1.0.6(2022-03-08)
-
修改样式 按钮自适应宽度
## 1.0.5(2022-03-08)
-
新增按钮 修改问题
## 1.0.4(2022-03-04)
-
增加空占位符"--"
## 1.0.3(2022-03-02)
-
新增表格斑马纹配置、列宽配置、表头显示配置
## 1.0.2(2022-03-02)
-
新增排序功能,优化样式
## 1.0.1(2022-03-01)
-
可以传入动态数据,可以对左边列表进行是否固定首列
## 1.0.0(2022-03-01)
-
初始化
\ No newline at end of file
uni_modules/zb-table/components/zb-table/components/table-checkbox.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"uni-table-checkbox"
@
click
.
stop=
"selected"
>
<view
v-if=
"!indeterminate"
class=
"checkbox__inner"
:class=
"
{'is-checked':isChecked,'is-disable':isDisabled}">
<view
class=
"checkbox__inner-icon"
></view>
</view>
<view
v-else
class=
"checkbox__inner checkbox--indeterminate"
>
<view
class=
"checkbox__inner-icon"
></view>
</view>
</view>
</
template
>
<
script
>
export
default
{
name
:
'TableCheckbox'
,
emits
:[
'checkboxSelected'
],
props
:
{
indeterminate
:
{
type
:
Boolean
,
default
:
false
},
checked
:
{
type
:
[
Boolean
,
String
],
default
:
false
},
disabled
:
{
type
:
Boolean
,
default
:
false
},
index
:
{
type
:
Number
,
default
:
-
1
},
cellData
:
{
type
:
Object
,
default
()
{
return
{}
}
}
},
watch
:{
checked
(
newVal
){
if
(
typeof
this
.
checked
===
'boolean'
){
this
.
isChecked
=
newVal
}
else
{
this
.
isChecked
=
true
}
},
indeterminate
(
newVal
){
this
.
isIndeterminate
=
newVal
}
},
data
()
{
return
{
isChecked
:
false
,
isDisabled
:
false
,
isIndeterminate
:
false
}
},
created
()
{
if
(
typeof
this
.
checked
===
'boolean'
){
this
.
isChecked
=
this
.
checked
}
this
.
isDisabled
=
this
.
disabled
},
methods
:
{
selected
()
{
if
(
this
.
isDisabled
)
return
this
.
isIndeterminate
=
false
this
.
isChecked
=
!
this
.
isChecked
console
.
log
(
'==='
,
this
.
indeterminate
,
this
.
isChecked
)
this
.
$emit
(
'checkboxSelected'
,
{
checked
:
this
.
isChecked
,
data
:
this
.
cellData
})
}
}
}
</
script
>
<
style
lang=
"scss"
>
$checked-color
:
#007aff
;
$border-color
:
#DCDFE6
;
$disable
:
0
.4
;
.uni-table-checkbox
{
display
:
flex
;
flex-direction
:
row
;
align-items
:
center
;
justify-content
:
center
;
position
:
relative
;
margin
:
5px
0
;
cursor
:
pointer
;
// 多选样式
.checkbox__inner
{
/* #ifndef APP-NVUE */
flex-shrink
:
0
;
box-sizing
:
border-box
;
/* #endif */
position
:
relative
;
width
:
16px
;
height
:
16px
;
border
:
1px
solid
$border-color
;
border-radius
:
2px
;
background-color
:
#fff
;
z-index
:
1
;
.checkbox__inner-icon
{
position
:
absolute
;
/* #ifdef APP-NVUE */
top
:
2px
;
/* #endif */
/* #ifndef APP-NVUE */
top
:
2px
;
/* #endif */
left
:
5px
;
height
:
7px
;
width
:
3px
;
border
:
1px
solid
#fff
;
border-left
:
0
;
border-top
:
0
;
opacity
:
0
;
transform-origin
:
center
;
transform
:
rotate
(
45deg
);
box-sizing
:
content-box
;
}
&
.checkbox--indeterminate
{
border-color
:
$checked-color
;
background-color
:
$checked-color
;
.checkbox__inner-icon
{
position
:
absolute
;
opacity
:
1
;
transform
:
rotate
(
0deg
);
height
:
2px
;
top
:
0
;
bottom
:
0
;
margin
:
auto
;
left
:
0px
;
right
:
0px
;
bottom
:
0
;
width
:
auto
;
border
:
none
;
border-radius
:
2px
;
transform
:
scale
(
0
.5
);
background-color
:
#fff
;
}
}
&
:hover
{
border-color
:
$checked-color
;
}
// 禁用
&
.is-disable
{
/* #ifdef H5 */
cursor
:
not
-
allowed
;
/* #endif */
background-color
:
#F2F6FC
;
border-color
:
$border-color
;
}
// 选中
&
.is-checked
{
border-color
:
$checked-color
;
background-color
:
$checked-color
;
.checkbox__inner-icon
{
opacity
:
1
;
transform
:
rotate
(
45deg
);
}
// 选中禁用
&
.is-disable
{
opacity
:
$disable
;
}
}
}
}
</
style
>
uni_modules/zb-table/components/zb-table/components/table-h5-summary.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"table-h5-footer top-header-uni"
:style=
"
{paddingRight:`${scrollbarSize}px`}">
<scroll-view
class=
"zb-table-headers"
@
scroll=
"handleFooterTableScrollLeft"
scroll-x=
"true"
scroll-y=
"false"
id=
"tableFooterHeaders"
scroll-anchoring=
"true"
:scroll-left=
"headerFooterTableLeft"
style=
"padding-bottom: 0px;
background: #fafafa;height: 100%"
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-thead"
style=
"position: relative;"
>
<view
class=
"item-tr"
>
<view
class=
"item-th"
:style=
"
{
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
v-for="(item,index) in transColumns" :key="index">
{{
sums
[
index
]
}}
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</
template
>
<
script
>
import
summary
from
'../js/summary.js'
export
default
{
name
:
'table-footer'
,
mixins
:[
summary
],
}
</
script
>
<
style
lang=
"scss"
scoped
>
.table-h5-footer
{
background
:
#fafafa
;
/*每个页面公共css */
scroll-view
:
:-
webkit-scrollbar
{
display
:
none
!
important
;
width
:
0
!
important
;
height
:
0
!
important
;
-webkit-appearance
:
none
;
background
:
transparent
;
}
//第二种
::-webkit-scrollbar
{
display
:
none
;
}
.item-tr
{
display
:
flex
;
}
.item-th
{
padding-left
:
8px
;
line-height
:
39px
;
height
:
40px
;
//display: flex;
//align-items: center;
box-sizing
:
border-box
;
flex-shrink
:
0
;
width
:
100px
;
padding-right
:
20px
;
word-break
:
keep-all
;
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
}
}
</
style
>
uni_modules/zb-table/components/zb-table/components/table-side-summary.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"zb-table-header"
style=
"display: flex;"
>
<view
class=
"item-tr"
>
<view
class=
'item-td'
:style=
"
{
width:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
:key="`15255966555${index}`"
v-for="(item,index) in fixedLeftColumns">
<template
>
{{
sums
[
index
]
}}
</
template
>
</view>
</view>
</view>
</template>
<
script
>
import
summary
from
'../js/summary.js'
export
default
{
mixins
:[
summary
]
}
</
script
>
<
style
lang=
"scss"
scoped
>
.zb-table-header
{
overflow
:
hidden
;
background
:
#fafafa
;
.item-th
{
padding-left
:
8px
;
line-height
:
39px
;
height
:
40px
;
//display: flex;
//align-items: center;
box-sizing
:
border-box
;
}
}
.item-tr
{
display
:
flex
;
box-sizing
:
border-box
;
}
.item-td
{
flex-shrink
:
0
;
width
:
100px
;
padding-left
:
8px
;
height
:
40px
;
line-height
:
40px
;
padding-right
:
20px
;
box-sizing
:
border-box
;
word-break
:
keep-all
;
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
background
:
rgb
(
250
,
250
,
250
);
}
</
style
>
uni_modules/zb-table/components/zb-table/components/table-summary.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"zb-table-footer"
style=
"height: 40px;"
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-thead"
style=
"position: relative;"
>
<view
class=
"item-tr"
>
<view
:class=
"['item-th',index
<fixedLeftColumns
.
length
&&'
zb-stick-side
']"
:style=
"
{
left:`${item.left}px`,
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
v-for="(item,index) in transColumns" :key="index">
<template>
{{
sums
[
index
]
||
item
.
emptyString
}}
</
template
>
</view>
</view>
</view>
</view>
</view>
</template>
<
script
>
import
summary
from
'../js/summary.js'
export
default
{
mixins
:[
summary
]
}
</
script
>
<
style
lang=
"scss"
scoped
>
.zb-table-footer
{
background
:
#fafafa
;
width
:
fit-content
;
min-width
:
100%
;
position
:
sticky
;
bottom
:
0
;
z-index
:
2
;
.item-tr
{
display
:
flex
;
min-width
:
100%
;
}
.item-th
{
padding-left
:
8px
;
line-height
:
39px
;
height
:
40px
;
//display: flex;
//align-items: center;
box-sizing
:
border-box
;
flex-shrink
:
0
;
width
:
100px
;
padding-right
:
20px
;
word-break
:
keep-all
;
white-space
:
nowrap
;
overflow
:
hidden
;
text-overflow
:
ellipsis
;
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
}
.zb-table-fixed
{
min-width
:
100%
;
}
.zb-stick-side
{
position
:
sticky
;
bottom
:
0
;
left
:
0
;
z-index
:
2
;
//border-right: solid 1rpx #dbdbdb;
box-sizing
:
border-box
;
background
:
#fafafa
;
//box-shadow: 6px 0 6px -4px #ccc;
}
}
</
style
>
uni_modules/zb-table/components/zb-table/components/zb-load-more.vue
0 → 100644
View file @
dcd21c31
<
template
>
<view
class=
"zb-load-more"
>
<image
:src=
"base64Flower"
style=
""
class=
"loading-custom-image"
></image>
<text>
正在加载中...
</text>
</view>
</
template
>
<
script
>
const
base64Flower
=
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkBAMAAACCzIhnAAAAKlBMVEVHcEzDw8Ovr6+pqamUlJTCwsKenp61tbWxsbGysrLNzc2bm5u5ubmjo6MpovhuAAAACnRSTlMA/P79/sHDhiZS0DxZowAABBBJREFUWMPtl89rE0EUx7ctTXatB3MI1SWnDbUKPUgXqh4ED8Uf7KUVSm3ooVSpSii0Fn/gD4j4o+APiEoVmos9FO2celiqZVgwgaKHPQiCCkv+F99kM7Ozm5kxq1dfD91k9pPve9/3ZjbRNHHok/mKli4eIPNgSuRObuN9SqSEzM20iGnm0yIbqCuV7NSSSIV7uyPM6JMBYdeTOanh/QihJYZsUCSby+VkMj2AvOt0rAeQAwqE3lfKMZVlQCZk1QOCKkkVPadITCfIRNKxfoJI5+0OIFtJx14CMSg1mRSDko7VAfksRQzEbGYqxOJcVTWMCH2I1/IACNW0PWU2M8cmAVHtnH5mM1VRWtwKZjOd5JbF6s1IbaYqaotjNlPHgDAnlAizubTR6ovMYn052g/U5qcmOpi0WL8xTS/3IfSet5m8MEr5ajjF5le6dq/OJpobrdY0t3i9QgefWrxW9/1BLhk0E9m8FeUMhhXal499iD0eQRfDF+ts/tttORRerfp+oV7f4xJj82iUYm1Yzod+ZQEAlS/8mMBwKebVmCVp1f0JLS6zKd17+iwRKTARVg2SHtz3iEbBH+Q+U28zW2Jiza8Tjb1YFoYZMsJyjDqp3M9XBQdSdPLFdxEpvOB37JrHcmR/y9+LgoTlCFGZEa2sc6d4PGlweEa2JSVPoVm+IfGG3ZL037iV9oH+P+Jxc4HGVflNq1M0pivao/EopO4b/ojVCP9GjmiXOeS0DOn1o/iiccT4ORnyvBGF3yUywkQajW4Ti0SGuiy/wVSg/L8w+X/8Q+hvUx8Xd90z4oV5a1i88MbFWHz0WZZ1UrTwBGPX3Rat9AFiXRMRjoMdIdJLEOt2h7jrYOzgOamKZSWSNspOS0X8SAqRYmxRL7sg4eLzYmNehcxh3uoyud/BH2Udux4ywxFTc1xC7Mgf4vMhc5S+kSH3Y7yj+qpwIWSoPTVCOOPVthGx9FbGqrwFw6wSFxJr+17zeKcztt3u+2roAEVgUjDd+AHGuxHy2rZHaa8JMkTHEeyi85ANPO9j9BVuBRD2FY5LDMo/Sz/2hReqGIs/KiFin+CsPsYO/yvM3jL2vE8EbX7/Bf8ejtr2GLN65bioAdgLd8Bis/mD5GmP2qeqyo2ZwQEOtAjRIDH7mBKpUcMoApbZJ5UIxkEwxyMZyMxW/uKFvHCFR3SSmerHyDNQ2dF4JG6zIMpBgLfjSF9x1D6smFcYnGApjmSLICO3ecCDWrQ48geba9DI3STy2i7ax6WIB62fSyIZIiO3GFQqSURp8wCo7GhJBGwuSovJBNjb7kT6FPVnIa9qJ2Ko+l9mefGIdinaMp0yC1URYiwsdfNE45EuA5Cx9EhalfvN5s+UyItm81vaB3p4joniN+SCP7Qc1hblAAAAAElFTkSuQmCC'
;
export
default
{
data
(){
return
{
base64Flower
}
}
}
</
script
>
<
style
lang=
"scss"
scoped
>
.zb-load-more
{
width
:
100%
;
position
:
absolute
;
bottom
:
0
;
left
:
0
;
z-index
:
999
;
background
:
white
;
display
:
flex
;
height
:
40px
;
flex-shrink
:
0
;
align-items
:
center
;
justify-content
:
center
;
.loading-custom-image
{
color
:
#a4a4a4
;
margin-right
:
8rpx
;
width
:
24px
;
height
:
24px
;
/* #ifndef APP-NVUE */
animation
:
loading-circle
1s
linear
infinite
;
/* #endif */
}
@keyframes
loading-circle
{
0
%
{
-webkit-transform
:
rotate
(
0deg
);
transform
:
rotate
(
0deg
);
}
100
%
{
-webkit-transform
:
rotate
(
360deg
);
transform
:
rotate
(
360deg
);
}
}
}
</
style
>
uni_modules/zb-table/components/zb-table/js/summary.js
0 → 100644
View file @
dcd21c31
export
default
{
props
:{
scrollbarSize
:{
type
:
Number
,
default
:
0
},
fixedLeftColumns
:{
type
:
Array
,
default
:()
=>
[]
},
data
:{
type
:
Array
,
default
:()
=>
[]
},
transColumns
:{
type
:
Array
,
default
:()
=>
[]
},
border
:{
type
:
Boolean
,
default
:
false
},
showSummary
:{
type
:
Boolean
,
default
:
false
},
summaryMethod
:{
type
:
Function
},
sumText
:{
type
:
String
,
default
:
'合计'
},
headerFooterTableLeft
:{
type
:
Number
,
default
:
0
},
handleFooterTableScrollLeft
:
Function
,
},
data
(){
return
{
sums
:[]
}
},
watch
:{
'data'
:{
deep
:
true
,
immediate
:
true
,
handler
(
newValue
,
oldValue
){
let
sums
=
[];
if
(
this
.
summaryMethod
)
{
sums
=
this
.
summaryMethod
({
columns
:
this
.
transColumns
,
data
:
this
.
data
});
}
else
{
this
.
transColumns
.
forEach
((
column
,
index
)
=>
{
if
(
index
===
0
)
{
sums
[
index
]
=
this
.
sumText
;
return
;
}
const
values
=
this
.
data
.
map
(
item
=>
Number
(
item
[
column
.
name
]));
const
precisions
=
[];
let
notNumber
=
true
;
values
.
forEach
(
value
=>
{
if
(
!
isNaN
(
value
))
{
notNumber
=
false
;
let
decimal
=
(
''
+
value
).
split
(
'.'
)[
1
];
precisions
.
push
(
decimal
?
decimal
.
length
:
0
);
}
});
const
precision
=
Math
.
max
.
apply
(
null
,
precisions
);
if
(
!
notNumber
)
{
sums
[
index
]
=
values
.
reduce
((
prev
,
curr
)
=>
{
const
value
=
Number
(
curr
);
if
(
!
isNaN
(
value
))
{
return
parseFloat
((
prev
+
curr
).
toFixed
(
Math
.
min
(
precision
,
20
)));
}
else
{
return
prev
;
}
},
0
);
}
else
{
sums
[
index
]
=
''
;
}
});
}
this
.
sums
=
sums
},
}
}
}
uni_modules/zb-table/components/zb-table/js/util.js
0 → 100644
View file @
dcd21c31
/**
* 获取滚动条宽度
*/
let
cached
=
undefined
;
export
const
getScrollbarSize
=
fresh
=>
{
// #ifdef H5
if
(
fresh
||
cached
===
undefined
)
{
let
inner
=
document
.
createElement
(
"div"
);
let
innerStyle
=
inner
.
style
;
innerStyle
.
width
=
"100%"
;
innerStyle
.
height
=
"200px"
;
let
outer
=
document
.
createElement
(
"div"
);
let
outerStyle
=
outer
.
style
;
outerStyle
.
position
=
"absolute"
;
outerStyle
.
top
=
0
;
outerStyle
.
left
=
0
;
outerStyle
.
pointerEvents
=
"none"
;
outerStyle
.
width
=
"200px"
;
outerStyle
.
height
=
"150px"
;
outerStyle
.
visibility
=
"hidden"
;
outer
.
appendChild
(
inner
);
document
.
body
.
appendChild
(
outer
);
// 设置子元素超出部分隐藏
outerStyle
.
overflow
=
"hidden"
;
let
width1
=
inner
.
offsetWidth
;
// 设置子元素超出部分滚动
outer
.
style
.
overflow
=
"scroll"
;
let
width2
=
inner
.
offsetWidth
;
if
(
width1
===
width2
)
{
width2
=
outer
.
clientWidth
;
}
document
.
body
.
removeChild
(
outer
);
cached
=
width1
-
width2
;
}
//#endif
return
cached
;
};
uni_modules/zb-table/components/zb-table/zb-table.vue
0 → 100644
View file @
dcd21c31
<
template
>
<!-- #ifdef H5 || APP-PLUS -->
<view
:class=
"['zb-table','zb-table-fixed-header',!border&&(bodyTableLeft>50||headerTableLeft>50)&&'scroll-left-fixed']"
>
<view
class=
"zb-table-content"
style=
"flex: 1"
>
<view
class=
"zb-table-scroll"
style=
"height: 100%;"
>
<template
v-if=
"showHeader"
>
<view
class=
"zb-table-header top-header-uni"
>
<scroll-view
class=
"zb-table-headers"
@
scroll=
"handleTableScrollLeft"
scroll-x=
"true"
scroll-y=
"false"
id=
"tableHeaders"
scroll-anchoring=
"true"
:scroll-left=
"headerTableLeft"
style=
"
height: 100%"
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-thead"
style=
"position: relative;"
>
<view
class=
"item-tr"
>
<view
@
click
.
stop=
"sortAction(item,index)"
class=
"item-th"
:style=
"[
{
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
},getHeaderCellStyle(item,index)]"
v-for="(item,index) in transColumns" :key="index">
<template
v-if=
"item.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
:indeterminate=
"indeterminate"
:checked=
"checkedAll"
@
checkboxSelected=
"checkboxSelectedAll"
></tableCheckbox>
</view>
</
template
>
<
template
v-else
>
{{
item
.
label
}}
<view
class=
"sorter-table"
v-if=
"item.sorter"
>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_asc'&&`sorting$
{item.sorterMode||''}`]">
</view>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_desc'&&`sorting$
{item.sorterMode||''}`]">
</view>
</view>
</
template
>
</view>
<view
v-if=
"scrollbarSize"
class=
"item-th "
:style=
"{
borderTop:`${border?'1px solid #e8e8e8':''}`,
padding:0,
width:`${scrollbarSize}px`,
}"
>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<
template
v-if=
"!data.length"
>
<view
class=
"no-data"
>
暂无数据~~
</view>
</
template
>
<scroll-view
class=
"zb-table-body"
ref=
"tableBody"
scroll-x=
"true"
scroll-y=
"true"
id=
"tableBody"
:lower-threshold=
"40"
:upper-threshold=
"10"
@
scrolltolower=
"scrolltolower"
@
scrolltoupper=
"(e)=>debounce(scrollToLeft)(e)"
@
scroll=
"handleBodyScroll"
:scroll-left=
"bodyTableLeft"
:scroll-top=
"bodyScrollTop"
:style=
" `height: calc(100% - ${showSummary?80:40}px)`"
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-tbody"
>
<view
:class=
"['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
@
click
.
stop=
"rowClick(item,index)"
v-for=
"(item,index) in transData"
:key=
"item.key"
>
<view
:style=
"[{
width:`${ite.width?ite.width:'100'}px`,
flex:i===transColumns.length-1?1:'none',
minWidth:`${ite.width?ite.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:ite.align||'left',
},cellStyle&&getCellStyle(item,ite,index,i)]"
@
click=
"cellClick(item,index,ite)"
:class=
"['item-td',stripe?(index % 2) != 0?'odd':'even':'']"
v-for=
"(ite,i) in transColumns"
:key=
"i"
>
<
template
v-if=
"ite.type==='operation'"
>
<view
style=
"display: flex;align-items: center;height: 100%"
>
<view
v-for=
"ren,ind in permission(item,ite.renders,index)"
:key=
"ind"
@
click
.
stop=
"$emit(ren.func,item,index)"
:style=
"
{
display:'flex',
alignItems: 'center',
marginRight:ite.renders.length>1?'8px':'0'
}">
<template
v-if=
"ren.type==='custom'"
>
<view
:class=
"ren.class||''"
style=
"cursor: pointer"
>
{{
ren
.
name
}}
</view>
</
template
>
<
template
v-else
>
<button
:class=
"ren.class||''"
:type=
"ren.type||'primary'"
:size=
"ren.size||'mini'"
>
{{
ren
.
name
}}
</button>
</
template
>
</view>
</view>
</template>
<
template
v-else-if=
"ite.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
@
checkboxSelected=
"(e)=>checkboxSelected(e,item)"
:cellData=
"item"
:checked=
"item.checked"
/>
</view>
</
template
>
<
template
v-else-if=
"ite.type==='index'"
>
{{
index
+
1
}}
</
template
>
<
template
v-else-if=
"ite.type==='img'"
>
<view
class=
"checkbox-item"
>
<template
v-if=
"item[ite.name]"
>
<image
@
click
.
stop=
"previewImage(item,item[ite.name],iImage)"
v-for=
"iImageTem,iImage in imgs(item[ite.name])"
:show-menu-by-longpress=
"false"
:key=
"iImage"
:src=
"iImageTem"
style=
"width: 40px;height:30px; "
mode=
"aspectFit"
></image>
</
template
>
<text
v-else
>
{{ite.emptyString}}
</text>
</view>
</template>
<
template
v-else
>
<!--
{{
ite
.
filters
?
itemFilter
(
item
,
ite
):(
item
[
ite
.
name
]
==
null
||
item
[
ite
.
name
]
===
''
)?
ite
.
emptyString
:
item
[
ite
.
name
]
}}
-->
{{
ite
.
filters
?
itemFilter
(
item
,
ite
):
formatterAction
(
item
,
ite
,
index
,
i
)
}}
</
template
>
</view>
</view>
</view>
</view>
</scroll-view>
<table-h5-summary
:scrollbarSize=
"scrollbarSize"
:data=
"data"
:handleFooterTableScrollLeft=
"handleFooterTableScrollLeft"
:headerFooterTableLeft=
"headerFooterTableLeft"
v-if=
"showSummary"
:showSummary=
"showSummary"
:transColumns=
"transColumns"
:border=
"border"
:summary-method=
"summaryMethod"
:sumText=
"sumText"
:fixedLeftColumns=
"fixedLeftColumns"
/>
</view>
<view
class=
"zb-table-fixed-left"
v-if=
"isFixedLeft"
:style=
" {height: `calc(100% - ${scrollbarSize}px)`}"
>
<
template
v-if=
"showHeader"
>
<view
class=
"zb-table-header"
style=
"display: flex"
>
<view
class=
"item-tr"
style=
""
@
click
.
stop=
"rowClick(item,index)"
v-for=
"(item,index) in fixedLeftColumns"
:key=
"index"
>
<view
:style=
"
{
width:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
@click.stop="sortAction(item,index)"
class="item-th"
>
<template
v-if=
"item.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
:indeterminate=
"indeterminate"
:checked=
"checkedAll"
@
checkboxSelected=
"checkboxSelectedAll"
></tableCheckbox>
</view>
</
template
>
<
template
v-else
>
{{
item
.
label
}}
<view
class=
"sorter-table"
v-if=
"item.sorter"
>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_asc'&&`sorting$
{item.sorterMode||''}`]">
</view>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_desc'&&`sorting$
{item.sorterMode||''}`]">
</view>
</view>
</
template
>
</view>
</view>
</view>
</template>
<scroll-view
scroll-y=
"true"
id=
"leftTableFixed"
:upper-threshold=
"15"
@
scrolltoupper=
"(e)=>scrollToFixedLeft(e)"
@
scroll=
"leftFixedScrollAction"
:scroll-top=
"leftFiexScrollTop"
class=
"zb-table-body-inner"
:style=
" `height: calc(100% - ${showSummary?80:40}px)`"
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-tbody"
>
<view
:class=
"['item-tr',stripe?(i % 2) != 0?'odd':'even':'',highlight&&isHighlight(ite,i)?'current-row':'']"
v-for=
"(ite,i) in transData"
@
click
.
stop=
"rowClick(ite,i)"
:key=
"ite.key"
style=
""
>
<view
class=
'item-td'
@
click=
"cellClick(ite,index,item)"
:style=
"[{
width:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
},cellStyle&&getCellStyle(ite,item,i,index)]"
:key=
"index"
v-for=
"(item,index) in fixedLeftColumns"
>
<
template
v-if=
"item.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
@
checkboxSelected=
"(e)=>checkboxSelected(e,ite)"
:cellData=
"ite"
:checked=
"ite.checked"
/>
</view>
</
template
>
<
template
v-else-if=
"item.type==='index'"
>
{{
i
+
1
}}
</
template
>
<
template
v-else
>
{{
ite
[
item
.
name
]
||
item
.
emptyString
}}
</
template
>
</view>
</view>
</view>
</view>
</scroll-view>
<table-side-summary
:scrollbarSize=
"scrollbarSize"
v-if=
"showSummary&&!(scrollbarSize>0)"
:data=
"data"
:showSummary=
"showSummary"
:transColumns=
"transColumns"
:border=
"border"
:summary-method=
"summaryMethod"
:sumText=
"sumText"
:fixedLeftColumns=
"fixedLeftColumns"
/>
</view>
</view>
<zb-load-more
v-if=
"isLoadMore&&!completeLoading"
/>
</view>
<!-- #endif -->
<!-- #ifndef H5 || APP-PLUS -->
<view
class=
"zb-table-applet"
>
<view
class=
"zb-table-content"
style=
"white-space: nowrap"
>
<scroll-view
<!
--
#
ifdef
MP-ALIPAY
--
>
@scroll="scrollAlipay"
<!-- #endif -->
@scrolltolower="scrolltolower"
<!-- #ifdef MP-ALIPAY -->
style=" height: 100%;overflow-x:scroll"
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
style=" height: 100%"
<!-- #endif -->
scroll-y="true"
scroll-x="true">
<view
class=
"zb-table-scroll"
>
<
template
v-if=
"showHeader"
>
<view
class=
"zb-table-header top-header-uni"
style=
""
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-thead"
style=
"position: relative;"
>
<view
class=
"item-tr"
>
<view
@
click
.
stop=
"sortAction(item,index)"
:class=
"['item-th',index
<fixedLeftColumns
.
length
&&'
zb-stick-side
']"
:style=
"
{
left:`${item.left}px`,
width:`${item.width?item.width:'100'}px`,
flex:index===transColumns.length-1?1:'none',
minWidth:`${item.width?item.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
borderTop:`${border?'1px solid #e8e8e8':''}`,
textAlign:item.align||'left'
}"
v-for="(item,index) in transColumns" :key="index">
<template
v-if=
"item.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
:indeterminate=
"indeterminate"
:checked=
"checkedAll"
@
checkboxSelected=
"checkboxSelectedAll"
></tableCheckbox>
</view>
</
template
>
<
template
v-else
>
{{
item
.
label
||
''
}}
<view
class=
"sorter-table"
v-if=
"item.sorter"
>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_asc'&&`sorting$
{item.sorterMode||''}`]">
</view>
<view
:class=
"['sorter-table-icon',item.sorterMode==='_desc'&&`sorting$
{item.sorterMode||''}`]">
</view>
</view>
</
template
>
</view>
</view>
</view>
</view>
</view>
</template>
<
template
v-if=
"!data.length"
>
<view
class=
"no-data"
>
暂无数据~~
</view>
</
template
>
<view
class=
"zb-table-fixed"
>
<view
class=
"zb-table-tbody"
>
<view
:class=
"['item-tr',highlight&&isHighlight(item,index)?'current-row':'']"
@
click
.
stop=
"rowClick(item,index)"
v-for=
"(item,index) in transData"
:key=
"item.key"
>
<view
:style=
"[{
left:`${ite.left}px`,
width:`${ite.width?ite.width:'100'}px`,
flex:i===transColumns.length-1?1:'none',
minWidth:`${ite.width?ite.width:'100'}px`,
borderRight:`${border?'1px solid #e8e8e8':''}`,
textAlign:ite.align||'left',
},getCellStyle(item,ite,index,i)]"
@
click=
"cellClick(item,index,ite)"
:class=
"['item-td', i <fixedLeftColumns.length&&'zb-stick-side',stripe?(index % 2) != 0?'odd':'even':'']"
v-for=
"(ite,i) in transColumns"
:key=
"i"
>
<
template
v-if=
"ite.type==='operation'"
>
<view
style=
"display: flex;align-items: center;height: 100%"
>
<view
v-for=
"ren,ind in permission(item,ite.renders,index)"
:key=
"ind"
@
click
.
stop=
"$emit(ren.func,item,index)"
:style=
"
{
display:'flex',
alignItems: 'center',
marginRight:ite.renders.length>1?'8px':'0'
}">
<template
v-if=
"ren.type==='custom'"
>
<view
:class=
"ren.class||''"
style=
"cursor: pointer"
>
{{
ren
.
name
}}
</view>
</
template
>
<
template
v-else
>
<button
:class=
"ren.class||''"
:type=
"ren.type||'primary'"
:size=
"ren.size||'mini'"
>
{{
ren
.
name
}}
</button>
</
template
>
</view>
</view>
</template>
<
template
v-else-if=
"ite.type==='selection'"
>
<view
class=
"checkbox-item"
>
<tableCheckbox
@
checkboxSelected=
"(e)=>checkboxSelected(e,item)"
:cellData=
"item"
:checked=
"item.checked"
/>
</view>
</
template
>
<
template
v-else-if=
"ite.type==='img'"
>
<template
v-if=
"item[ite.name]"
>
<view
class=
"checkbox-item"
@
click
.
stop
>
<image
@
click
.
stop=
"previewImage(iImageTem,item[ite.name],iImage)"
v-for=
"iImageTem,iImage in imgs(item[ite.name])"
:show-menu-by-longpress=
"false"
:key=
"iImage"
:src=
"iImageTem"
style=
"width: 40px;height:30px; "
mode=
"aspectFit"
></image>
</view>
</
template
>
<text
v-else
>
{{ite.emptyString}}
</text>
</template>
<
template
v-else-if=
"ite.type==='index'"
>
{{
index
+
1
}}
</
template
>
<
template
v-else
>
<!--
{{
ite
.
filters
?
itemFilter
(
item
,
ite
):(
item
[
ite
.
name
]
==
null
||
item
[
ite
.
name
]
===
''
)?
ite
.
emptyString
:
item
[
ite
.
name
]
}}
-->
{{
ite
.
filters
?
itemFilter
(
item
,
ite
):
formatterAction
(
item
,
ite
,
index
,
i
)
}}
</
template
>
</view>
</view>
</view>
</view>
<table-summary
v-if=
"showSummary"
:data=
"data"
:showSummary=
"showSummary"
:fixedLeftColumns=
"fixedLeftColumns"
:transColumns=
"transColumns"
:border=
"border"
:summary-method=
"summaryMethod"
:sumText=
"sumText"
/>
</view>
</scroll-view>
</view>
<zb-load-more
v-if=
"isLoadMore&&!completeLoading"
/>
</view>
<!-- #endif -->
</template>
<
script
>
import
TableCheckbox
from
'./components/table-checkbox.vue'
import
TableSummary
from
"./components/table-summary.vue"
;
import
TableSideSummary
from
"./components/table-side-summary.vue"
;
import
TableH5Summary
from
'./components/table-h5-summary'
import
ZbLoadMore
from
'./components/zb-load-more'
// #ifdef H5
import
{
getScrollbarSize
}
from
"./js/util"
;
// #endif
export
default
{
components
:{
TableCheckbox
,
TableSummary
,
TableSideSummary
,
TableH5Summary
,
ZbLoadMore
},
props
:{
highlight
:{
type
:
Boolean
,
default
:
false
},
itemDate
:{
type
:
Object
,
default
:()
=>
{}
},
columns
:{
type
:
Array
,
default
:()
=>
[]
},
showSummary
:{
type
:
Boolean
,
default
:
false
},
isShowLoadMore
:{
type
:
Boolean
,
default
:
false
},
data
:{
type
:
Array
,
default
:()
=>
[]
},
sumText
:{
type
:
String
,
default
:
'合计'
},
showHeader
:{
type
:
Boolean
,
default
:
true
},
border
:{
type
:
Boolean
,
default
:
false
},
stripe
:{
type
:
Boolean
,
default
:
true
},
fit
:{
type
:
Boolean
,
default
:
false
},
rowKey
:[
String
,
Function
],
summaryMethod
:
Function
,
pullUpLoading
:
Function
,
formatter
:
Function
,
cellStyle
:
Function
,
cellHeaderStyle
:
Function
,
permissionBtn
:
Function
,
},
computed
:{
loadMoreHeight
(){
return
this
.
isLoadMore
?
40
:
0
},
fixedLeftColumns
(){
let
arr
=
[]
for
(
let
i
=
0
;
i
<
this
.
columns
.
length
;
i
++
){
let
item
=
this
.
columns
[
i
]
if
(
item
.
fixed
){
arr
.
push
(
item
)
}
else
{
break
}
}
return
arr
},
imgs
(){
return
(
item
)
=>
{
return
typeof
item
===
'string'
?[
item
]:
item
}
},
itemfilters
(){
return
(
item
,
ite
)
=>
{
if
(
item
[
ite
.
name
]
==
null
){
return
ite
.
emptyString
}
return
item
[
ite
.
name
]
}
},
scrollbarSize
(){
// #ifdef H5
return
getScrollbarSize
()
// #endif
// #ifndef H5
return
0
// #endif
},
isFixedLeft
(){
if
(
!
this
.
columns
.
length
){
return
false
}
if
(
!
this
.
data
.
length
){
return
false
}
let
[
firstArr
]
=
this
.
columns
return
!!
firstArr
.
fixed
;
},
transColumns
(){
if
(
this
.
fit
){
this
.
columns
.
forEach
(
column
=>
{
if
(
column
.
type
===
"operation"
&&
column
.
renders
){
let
str
=
''
column
.
renders
.
map
((
item
)
=>
{
str
+=
item
.
name
})
column
.
width
=
this
.
getTextWidth
(
str
)
+
column
.
renders
.
length
*
40
}
else
if
(
column
.
type
===
"img"
){
}
else
if
(
column
.
type
===
"selection"
){
}
else
{
let
arr
=
[
this
.
getTextWidth
(
column
.
label
)]
this
.
data
.
forEach
(
data
=>
{
let
str
=
(
data
[
column
.
name
]
+
''
)
if
(
str
===
'undefined'
){
arr
.
push
(
30
)
}
else
{
let
width
=
this
.
getTextWidth
(
str
)
arr
.
push
(
width
)
}
})
column
.
width
=
Math
.
max
(...
arr
)
+
20
}
})
}
let
number
=
0
this
.
columns
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
type
===
"operation"
&&
item
.
renders
&&!
item
.
width
){
let
str
=
''
item
.
renders
.
map
((
item
)
=>
{
str
+=
item
.
name
})
item
.
width
=
this
.
getTextWidth
(
str
)
+
item
.
renders
.
length
*
40
}
if
(
item
.
type
===
"img"
){
if
(
!
item
.
width
){
let
arr
=
[]
let
widImg
=
this
.
getTextWidth
(
item
.
label
)
this
.
data
.
forEach
(
data
=>
{
if
(
data
[
item
.
name
]){
let
urls
=
typeof
data
[
item
.
name
]
===
'string'
?[
data
[
item
.
name
]]:
data
[
item
.
name
]
arr
.
push
(
urls
.
length
)
}
item
.
width
=
Math
.
max
(...
arr
)
*
40
+
widImg
})
}
}
if
(
item
.
fixed
){
if
(
index
===
0
){
item
.
left
=
0
number
+=
item
.
width
}
else
{
item
.
left
=
number
number
+=
item
.
width
}
}
item
.
emptyString
=
item
.
emptyString
||
'--'
})
return
this
.
columns
},
transData
(){
let
flag
=
this
.
columns
.
some
(
item
=>
item
.
type
===
'selection'
)
this
.
data
.
forEach
((
item
,
index
)
=>
{
if
(
flag
){
if
(
item
.
checked
){
if
(
!
this
.
selectArr
.
length
){
this
.
selectArr
.
push
(
item
)
}
}
}
if
(
this
.
rowKey
){
if
(
typeof
this
.
rowKey
===
'function'
){
item
.
key
=
Object
.
freeze
(
this
.
rowKey
(
item
))
||
Date
.
now
()
}
else
{
item
.
key
=
Object
.
freeze
(
item
[
this
.
rowKey
])
||
Date
.
now
()
}
}
else
{
item
.
key
=
index
}
})
if
(
flag
){
if
(
this
.
data
.
length
){
let
le
=
this
.
data
.
filter
(
item
=>
item
.
checked
).
length
if
(
le
){
if
(
le
===
this
.
data
.
length
){
this
.
checkedAll
=
true
}
else
{
this
.
indeterminate
=
true
}
}
else
{
this
.
checkedAll
=
false
this
.
indeterminate
=
false
this
.
selectArr
=
[]
}
}
else
{
this
.
checkedAll
=
false
this
.
indeterminate
=
false
this
.
selectArr
=
[]
}
}
return
this
.
data
},
isHighlight
(){
return
(
item
,
index
)
=>
{
if
(
this
.
rowKey
){
return
item
.
key
===
this
.
currentRow
[
'key'
]
}
else
{
return
index
===
this
.
currentRowIndex
}
}
},
getHeaderCellStyle
()
{
return
(
column
,
columnIndex
,
childIndex
)
=>
{
const
cellStyle
=
this
.
cellHeaderStyle
;
if
(
typeof
cellStyle
===
'function'
){
return
cellStyle
({
column
,
columnIndex
})
}
return
{}
}
},
getCellStyle
()
{
return
(
row
,
column
,
rowIndex
,
columnIndex
)
=>
{
const
cellStyle
=
this
.
cellStyle
;
if
(
typeof
cellStyle
===
'function'
){
return
cellStyle
({
row
,
column
,
rowIndex
,
columnIndex
})
}
return
{}
}
},
},
data
()
{
return
{
button
:[],
alipayScrollTop
:
0
,
alipayScrollOldTop
:
0
,
alipayFlag
:
false
,
bodyTableLeft
:
0
,
headerTableLeft
:
0
,
lastScrollLeft
:
0
,
isLoadMore
:
false
,
headerFooterTableLeft
:
0
,
leftFiexScrollTop
:
0
,
bodyScrollTop
:
0
,
currentDriver
:
null
,
currentDriver1
:
null
,
bodyTime
:
null
,
currentRowIndex
:
null
,
currentRow
:
{},
bodyTime1
:
null
,
headerTime
:
null
,
debounceTime
:
null
,
operation
:{},
completedFlag
:
false
,
selectArr
:[],
indeterminate
:
false
,
checkedAll
:
false
,
completeLoading
:
false
,
aliTime
:
null
,
}
},
created
(){
},
mounted
(){
// setTimeout(()=>{
// uni.createSelectorQuery().in(this).select(".top-header-uni").boundingClientRect( data => {
// console.log('data=======',data)
// //data 可以打印data输出看详细数据,有很多数据信息
// var left = data.width;//表示元素宽度
// }).exec();
// },1000)
},
beforeDestroy
(){
this
.
aliTime
&&
clearTimeout
(
this
.
aliTime
)
this
.
debounceTime
&&
clearTimeout
(
this
.
debounceTime
)
this
.
bodyTime1
&&
clearTimeout
(
this
.
bodyTime1
)
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
selectArr
=
[]
this
.
indeterminate
=
false
this
.
checkedAll
=
false
},
methods
:
{
clearSelection
(){
this
.
transData
.
forEach
(
item
=>
{
item
.
checked
=
false
})
this
.
selectArr
=
[]
this
.
indeterminate
=
false
this
.
checkedAll
=
false
},
formatterAction
(
row
,
column
,
rowIndex
,
columnIndex
){
if
(
column
.
formatter
&&
typeof
this
.
formatter
===
'function'
){
return
this
.
formatter
(
row
,
column
,
rowIndex
,
columnIndex
)
}
return
(
row
[
column
.
name
]
==
null
||
row
[
column
.
name
]
===
''
)?
column
.
emptyString
:
row
[
column
.
name
]
},
permission
(
item
,
renders
,
index
){
if
(
this
.
permissionBtn
&&
typeof
this
.
permissionBtn
===
'function'
){
return
this
.
permissionBtn
(
item
,
renders
,
index
)
}
return
renders
},
pullUpCompleteLoading
(
type
){
this
.
isLoadMore
=
false
if
(
type
===
'ok'
){
this
.
completeLoading
=
true
}
},
scrollAlipay
(
e
){
if
(
!
this
.
alipayScrollOldTop
){
this
.
alipayScrollOldTop
=
e
.
detail
.
scrollTop
}
this
.
aliTime
&&
clearTimeout
(
this
.
aliTime
)
this
.
aliTime
=
setTimeout
(()
=>
{
if
(
this
.
alipayFlag
&&
e
.
detail
.
scrollTop
>
this
.
alipayScrollOldTop
){
this
.
pullLoad
()
}
this
.
alipayFlag
=
false
this
.
alipayScrollOldTop
=
null
},
500
)
},
pullLoad
(){
if
(
this
.
isShowLoadMore
){
this
.
isLoadMore
=
true
this
.
$emit
(
'pullUpLoading'
)
let
that
=
this
this
.
pullUpLoading
&&
this
.
pullUpLoading
.
call
(
this
.
$parent
.
$parent
,
(
type
)
=>
{
that
.
isLoadMore
=
false
if
(
type
===
'ok'
){
that
.
completeLoading
=
true
}
})
}
},
scrolltolower
(
e
){
this
.
alipayFlag
=
true
if
(
e
.
detail
.
direction
===
'bottom'
){
this
.
pullLoad
()
}
// this.pullUpLoading.call(this.$parent)
},
previewImage
(
item
,
url
,
current
){
let
urls
=
typeof
url
===
'string'
?[
url
]:
url
uni
.
previewImage
({
current
,
urls
:
urls
})
},
resetHighlight
(){
this
.
currentRowIndex
=
null
this
.
currentRow
=
{}
},
cellClick
(
row
,
index
,
column
){
this
.
$emit
(
'cellClick'
,
row
,
index
,
column
)
},
rowClick
(
row
,
index
){
if
(
this
.
highlight
){
this
.
currentRowIndex
=
index
this
.
currentRow
=
row
this
.
$emit
(
'currentChange'
,
row
,
index
)
}
this
.
$emit
(
'rowClick'
,
row
,
index
)
},
checkboxSelectedAll
(
e
){
this
.
indeterminate
=
false
if
(
e
.
checked
){
this
.
selectArr
=
[]
this
.
checkedAll
=
true
this
.
data
.
forEach
(
item
=>
{
// this.$set(item,'checked',true)
item
.
checked
=
true
this
.
selectArr
.
push
(
item
)
})
}
else
{
this
.
checkedAll
=
false
this
.
data
.
forEach
(
item
=>
{
this
.
$set
(
item
,
'checked'
,
false
)
})
this
.
selectArr
=
[]
}
// #ifndef H5 || APP-PLUS
this
.
$forceUpdate
()
// #endif
this
.
$emit
(
'toggleAllSelection'
,
e
.
checked
,
this
.
selectArr
)
},
checkboxSelected
(
e
,
item
){
// #ifdef H5 || APP-PLUS
this
.
$set
(
item
,
'checked'
,
e
.
checked
)
// #endif
// #ifndef H5 || APP-PLUS
this
.
data
.
forEach
(
item
=>
{
if
(
item
.
key
===
e
.
data
.
key
){
item
.
checked
=
e
.
checked
}
})
// #endif
item
.
checked
=
e
.
checked
e
.
data
.
checked
=
e
.
checked
if
(
e
.
checked
){
this
.
selectArr
.
push
(
e
.
data
)
}
else
{
this
.
selectArr
=
this
.
selectArr
.
filter
(
item
=>
item
.
key
!==
e
.
data
.
key
)
}
if
(
this
.
selectArr
.
length
===
this
.
transData
.
length
){
this
.
indeterminate
=
false
this
.
checkedAll
=
true
}
else
{
this
.
indeterminate
=
true
this
.
checkedAll
=
false
}
if
(
!
this
.
selectArr
.
length
){
this
.
checkedAll
=
false
this
.
indeterminate
=
false
}
// #ifndef H5 || APP-PLUS
this
.
$forceUpdate
()
// #endif
this
.
$emit
(
'toggleRowSelection'
,
e
.
checked
,
this
.
selectArr
)
},
itemFilter
(
item
,
ite
){
if
(
ite
.
filters
&&
ite
.
name
){
let
key
=
item
[
ite
.
name
]
return
ite
.
filters
[
key
]
||
''
}
return
item
[
ite
.
name
]
||
ite
.
emptyString
},
// 默认字体为微软雅黑 Microsoft YaHei,字体大小为 14px
getTextWidth
(
str
)
{
if
(
str
.
length
<
3
){
return
40
}
let
regx
=
/^
[
0-9
]
+.
?[
0-9
]
*$/
let
flexWidth
=
0
for
(
const
char
of
str
)
{
if
((
char
>=
'A'
&&
char
<=
'Z'
)
||
(
char
>=
'a'
&&
char
<=
'z'
))
{
// 如果是英文字符,为字符分配8个单位宽度
flexWidth
+=
10
}
else
if
(
char
>=
'
\
u4e00'
&&
char
<=
'
\
u9fa5'
)
{
// 如果是中文字符,为字符分配15个单位宽度
flexWidth
+=
15
}
else
if
(
regx
.
test
(
char
)){
flexWidth
+=
9
}
else
{
// 其他种类字符,为字符分配8个单位宽度
flexWidth
+=
7
}
}
return
flexWidth
},
width
(
item
){
return
`
${
item
.
width
?
item
.
width
:
'100'
}
px`
},
showStripe
(
index
){
if
(
this
.
currentDriver
)
return
if
(
this
.
stripe
){
return
(
index
%
2
)
!=
0
?
'odd'
:
'even'
}
else
{
return
''
}
},
//验证字符串是否是数字
checkNumber
(
theObj
)
{
var
reg
=
/^
[
0-9
]
+.
?[
0-9
]
*$/
;
if
(
reg
.
test
(
theObj
))
{
return
true
;
}
return
false
;
},
isDate
(
data
){
if
(
isNaN
(
data
)
&&!
isNaN
(
Date
.
parse
(
data
))){
return
true
}
return
false
},
sortAction
(
item
,
index
){
if
(
!
item
.
sorter
){
return
false
}
this
.
$set
(
item
,
'sorterMode'
,
item
.
sorterMode
===
'_asc'
?
'_desc'
:
'_asc'
)
if
(
item
.
sorter
===
'custom'
){
this
.
$emit
(
'sort-change'
,
item
,
item
.
sorterMode
.
replace
(
'_'
,
''
),
index
)
}
else
{
this
.
sortData
(
item
)
}
// #ifndef H5 || APP-PLUS
this
.
$forceUpdate
()
// #endif
},
sortData
(
item
){
let
key
=
item
.
name
if
(
item
.
sorterMode
===
'_asc'
){
this
.
data
.
sort
((
a
,
b
)
=>
{
if
(
this
.
checkNumber
(
a
[
key
])){
return
a
[
key
]
-
b
[
key
]
}
if
(
this
.
isDate
(
a
[
key
])){
let
a1
=
new
Date
(
a
[
key
]).
getTime
()
let
b1
=
new
Date
(
b
[
key
]).
getTime
()
return
a1
-
b1
}
})
}
else
{
this
.
data
.
sort
((
a
,
b
)
=>
{
if
(
this
.
checkNumber
(
a
[
key
])){
return
b
[
key
]
-
a
[
key
]
}
if
(
this
.
isDate
(
a
[
key
])){
let
a1
=
new
Date
(
a
[
key
]).
getTime
()
let
b1
=
new
Date
(
b
[
key
]).
getTime
()
return
b1
-
a1
}
})
}
},
throttle
(
method
,
delay
=
60
){
let
time
=
null
return
(...
args
)
=>
{
if
(
!
time
){
time
=
setTimeout
(()
=>
{
method
(...
args
)
time
=
null
;
},
delay
)
}
}
},
debounce
(
method
,
delay
=
1000
){
return
(...
args
)
=>
{
this
.
debounceTime
&&
clearTimeout
(
this
.
debounceTime
)
this
.
debounceTime
=
setTimeout
(()
=>
{
method
(...
args
)
},
delay
)
}
},
handleBodyScroll
(
e
){
if
(
this
.
currentDriver
&&
this
.
currentDriver
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver
=
e
.
currentTarget
.
id
this
.
headerTableLeft
=
e
.
detail
.
scrollLeft
this
.
headerFooterTableLeft
=
e
.
detail
.
scrollLeft
this
.
leftFiexScrollTop
=
e
.
detail
.
scrollTop
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver
=
null
},
200
)
},
leftFixedScrollAction
(
e
){
if
(
this
.
currentDriver
&&
this
.
currentDriver
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver
=
e
.
currentTarget
.
id
this
.
bodyScrollTop
=
e
.
detail
.
scrollTop
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver
=
null
},
200
)
},
scrollToLeft
(
e
){
if
(
this
.
currentDriver1
&&
this
.
currentDriver1
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver1
=
e
.
currentTarget
.
id
if
(
e
.
detail
.
direction
===
'left'
&&
this
.
headerTableLeft
<
10
){
this
.
headerTableLeft
=
0
}
else
if
(
e
.
detail
.
direction
===
'top'
&&
this
.
leftFiexScrollTop
<
10
){
this
.
leftFiexScrollTop
=
0
}
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver1
=
null
},
200
)
},
scrollToFixedLeft
(
e
){
if
(
this
.
currentDriver1
&&
this
.
currentDriver1
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver1
=
e
.
currentTarget
.
id
if
(
e
.
detail
.
direction
===
'top'
&&
this
.
bodyScrollTop
<
10
){
this
.
bodyScrollTop
=
0
}
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver1
=
null
},
200
)
},
handleTableScrollLeft
(
e
,
type
){
if
(
this
.
currentDriver
&&
this
.
currentDriver
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver
=
e
.
currentTarget
.
id
this
.
bodyTableLeft
=
e
.
detail
.
scrollLeft
this
.
headerFooterTableLeft
=
e
.
detail
.
scrollLeft
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver
=
null
},
200
)
},
handleFooterTableScrollLeft
(
e
){
if
(
this
.
currentDriver
&&
this
.
currentDriver
!==
e
.
currentTarget
.
id
)
return
this
.
currentDriver
=
e
.
currentTarget
.
id
this
.
bodyTableLeft
=
e
.
detail
.
scrollLeft
this
.
headerTableLeft
=
e
.
detail
.
scrollLeft
this
.
bodyTime
&&
clearTimeout
(
this
.
bodyTime
)
this
.
bodyTime
=
setTimeout
(()
=>
{
this
.
currentDriver
=
null
},
200
)
}
}
}
</
script
>
<
style
lang=
"scss"
>
.zb-table-fixed-left
{
/*去除左边滚动条 */
scroll-view
:
:-
webkit-scrollbar
{
display
:
none
!
important
;
width
:
0
!
important
;
height
:
0
!
important
;
-webkit-appearance
:
none
;
background
:
transparent
;
}
}
.zb-table-header
{
///*去除头部滚动条 */
scroll-view
:
:-
webkit-scrollbar
{
display
:
none
!
important
;
width
:
0
!
important
;
height
:
0
!
important
;
-webkit-appearance
:
none
;
background
:
transparent
;
}
}
</
style
>
<
style
lang=
"scss"
scoped
>
.sorter-table
{
position
:
absolute
;
right
:
6px
;
top
:
50%
;
transform
:translateY
(
-50
%
)
;
.sorter-table-icon
{
width
:
0
;
height
:
0
;
color
:
#dcdcdc
;
border-right
:
4px
solid
transparent
;
border-left
:
4px
solid
transparent
;
}
.sorter-table-icon
:first-child
{
border-bottom
:
5px
solid
currentColor
;
}
.sorter-table-icon
:last-child
{
margin-top
:
1
.5px
;
border-top
:
5px
solid
currentColor
;
}
.sorting_desc
{
color
:
#2979ff
;
}
.sorting_asc
{
color
:
#2979ff
;
}
}
.checkbox-item
{
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
width
:
100%
;
height
:
100%
}
.no-data
{
width
:
100%
;
height
:
80rpx
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
border-bottom
:
1px
solid
#e8e8e8
;
}
.item-th
{
position
:
relative
;
flex-shrink
:
0
;
width
:
100px
;
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
transition
:
background
0
.3s
;
padding-right
:
20px
;
word-break
:keep-all
;
/* 不换行 */
white-space
:nowrap
;
/* 不换行 */
overflow
:hidden
;
/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow
:ellipsis
;
/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
overflow-wrap
:
break-word
;
}
.zb-table
{
height
:
100%
;
overflow
:
hidden
;
width
:
100%
;
display
:
flex
;
flex-direction
:
column
;
font-size
:
12px
;
position
:
relative
;
.zb-table-content
{
//height: 100%;
//flex: 1;
position
:
relative
;
overflow
:
hidden
;
}
.zb-table-fixed
{
min-width
:
100%
;
}
.zb-table-body
{
position
:
relative
;
background
:
#fff
;
transition
:
opacity
0
.3s
;
}
.item-tr
{
display
:
flex
;
//height: 41px;
}
.item-td
{
flex-shrink
:
0
;
width
:
100px
;
padding-left
:
8px
;
height
:
40px
;
line-height
:
40px
;
padding-right
:
20px
;
box-sizing
:
border-box
;
word-break
:keep-all
;
/* 不换行 */
white-space
:nowrap
;
/* 不换行 */
overflow
:hidden
;
/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow
:ellipsis
;
/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
//transition: background 0.3s;
}
.zb-table-fixed-left
.zb-table-header
{
overflow-y
:
hidden
;
}
.zb-table-header
{
overflow
:
hidden
;
background
:
#fafafa
;
.item-th
{
padding-left
:
8px
;
line-height
:
39px
;
height
:
40px
;
//display: flex;
//align-items: center;
box-sizing
:
border-box
;
}
}
.zb-table-fixed-left
.zb-table-fixed
{
background
:
#fff
;
}
.zb-table-fixed-right
.zb-table-fixed
{
background
:
#fff
;
}
.zb-table-body-inner
{
height
:
100%
;
// overflow: scroll;
}
.zb-table-fixed-left
{
position
:
absolute
;
top
:
0
;
z-index
:
1
;
overflow
:
hidden
;
border-radius
:
0
;
height
:
100%
;
//transition: box-shadow 0.3s ease;
}
.odd
{
background-color
:rgba
(
249
,
249
,
249
,
0
.6
)
;
//height: 100%;
width
:
100%
;
}
.even
{
background-color
:white
;
//height: 100%;
width
:
100%
;
}
}
.scroll-left-fixed
{
.zb-table-fixed-left
{
left
:
0
;
box-shadow
:
6px
0
6px
-4px
#ccc
;
}
}
.zb-table-applet
{
height
:
100%
;
//overflow: hidden;
width
:
100%
;
position
:
relative
;
display
:
flex
;
flex-direction
:
column
;
font-size
:
12px
;
.zb-table-content
{
//height: 100%;
flex
:
1
;
overflow
:
hidden
;
position
:
relative
;
}
.zb-table-fixed
{
min-width
:
100%
;
width
:
fit-content
;
}
.zb-table-body
{
position
:
relative
;
background
:
#fff
;
transition
:
opacity
0
.3s
;
}
.item-tr
{
display
:
flex
;
//height: 41px;
}
.item-td
{
flex-shrink
:
0
;
width
:
100px
;
padding-left
:
8px
;
height
:
40px
;
line-height
:
40px
;
padding-right
:
20px
;
box-sizing
:
border-box
;
word-break
:keep-all
;
/* 不换行 */
white-space
:nowrap
;
/* 不换行 */
overflow
:hidden
;
/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow
:ellipsis
;
/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
overflow-wrap
:
break-word
;
border-bottom
:
1px
solid
#e8e8e8
;
//transition: background 0.3s;
}
.zb-table-header
{
//overflow: hidden;
position
:
sticky
;
top
:
0
;
z-index
:
2
;
//width: fit-content;
.item-th
{
padding-left
:
8px
;
line-height
:
39px
;
height
:
40px
;
box-sizing
:
border-box
;
background
:
#fafafa
;
}
.zb-stick-side
{
position
:
sticky
;
top
:
0
;
left
:
0
;
z-index
:
2
;
//border-right: solid 1rpx #dbdbdb;
box-sizing
:
border-box
;
background
:
#fafafa
;
//box-shadow: 6px 0 6px -4px #ccc;
}
}
.zb-table-fixed-left
.zb-table-fixed
{
background
:
#fff
;
}
.zb-table-fixed-right
.zb-table-fixed
{
background
:
#fff
;
}
.zb-table-fixed-header
.zb-table-body-inner
{
height
:
100%
;
// overflow: scroll;
}
.zb-table-fixed-left
{
position
:
absolute
;
top
:
0
;
z-index
:
1
;
overflow
:
hidden
;
border-radius
:
0
;
height
:
100%
;
//transition: box-shadow 0.3s ease;
}
.scroll-left-fixed
{
.zb-table-fixed-left
{
left
:
0
;
box-shadow
:
6px
0
6px
-4px
#ccc
;
}
}
.odd
{
background-color
:rgba
(
249
,
249
,
249
,
0
.6
)
;
//height: 100%;
width
:
100%
;
}
.even
{
background-color
:white
;
//height: 100%;
width
:
100%
;
}
.zb-table-tbody
{
.zb-stick-side
{
position
:
sticky
;
left
:
0
;
z-index
:
1
;
box-sizing
:
border-box
;
background
:white
;
//box-shadow: 6px 0 6px -2px #ccc;
}
.odd
{
background
:
#f9f9f9
;
//height: 100%;
width
:
100%
;
}
.even
{
background
:white
;
//height: 100%;
width
:
100%
;
}
}
.current-row
{
.item-td
{
background-color
:
#ecf5ff
;
}
}
}
.current-row
{
.item-td
{
background-color
:
#ecf5ff
;
}
}
.zb-table-header
{
height
:
40px
;
}
.scrollPosition
{
position
:
absolute
;
right
:
0
;
top
:
0
;
height
:
100%
;
background
:
red
;
z-index
:
999
;
}
</
style
>
uni_modules/zb-table/package.json
0 → 100644
View file @
dcd21c31
{
"id"
:
"zb-table"
,
"displayName"
:
"zb-table(多功能表格)"
,
"version"
:
"1.2.18"
,
"description"
:
"表格组件 支持固定表头和首列、上拉加载更多、及固定多列,表格自适应内容,排序,多选checkbox、可点击删除,编辑、合计功能,兼容多端"
,
"keywords"
:
[
"table"
,
"表格"
,
"固定表头、固定首列、多列"
,
"上拉加载更多、"
,
"排序、自适应列宽、多选checkbox、编辑、删除、按钮、合计"
],
"repository"
:
"https://github.com/zouzhibin/zb-table.git"
,
"engines"
:
{
"HBuilderX"
:
"^3.1.0"
},
"dcloudext"
:
{
"sale"
:
{
"regular"
:
{
"price"
:
"0.00"
},
"sourcecode"
:
{
"price"
:
"0.00"
}
},
"contact"
:
{
"qq"
:
""
},
"declaration"
:
{
"ads"
:
"无"
,
"data"
:
"无"
,
"permissions"
:
"无"
},
"npmurl"
:
""
,
"type"
:
"component-vue"
},
"uni_modules"
:
{
"dependencies"
:
[],
"encrypt"
:
[],
"platforms"
:
{
"cloud"
:
{
"tcb"
:
"y"
,
"aliyun"
:
"y"
},
"client"
:
{
"Vue"
:
{
"vue2"
:
"y"
,
"vue3"
:
"y"
},
"App"
:
{
"app-vue"
:
"y"
,
"app-nvue"
:
"u"
},
"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"
},
"快应用"
:
{
"华为"
:
"y"
,
"联盟"
:
"y"
}
}
}
}
}
\ No newline at end of file
uni_modules/zb-table/readme.md
0 → 100644
View file @
dcd21c31
## 介绍
基于uni-app开发的一个普通的表格组件,功能有固定首列和表头、排序、操作按钮、
table 表格 固定表头、固定首列、多列 上拉加载更多、 排序、自适应列宽、多选checkbox、编辑、删除、按钮、合计
已用于生产环境
微信=》 19550102670 拉进群
## -- github 第一时间会更新到github,永远保持最新,有啥想法的可以提PR,共同开发 [地址](https://github.com/zouzhibin/zb-ui)
## 友情链接
### 在线预览点击 —— [企业级、通用型中后台前端解决方案 ](https://yuanzbz.gitee.io/vue-admin-perfect/#/login?redirect=/home)
### vue-admin-perfect —— [企业级、通用型中后台前端解决方案(基于vue3.0+TS+Element-Plus 最新版,同时支持电脑,手机,平板)](https://github.com/zouzhibin/vue-admin-perfect)
## table 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |是否必须|
| ------ | ------ | ------ | ------ | ------ |------ |
| data | 显示的数据 | array |-- | -- |必须 |
| column | 显示的列数据 | array |-- | -- |必须 |
| stripe | 是否为斑马纹 table| boolean | - |false | 否 |
| fit | 列的宽度是否自撑开 | boolean |true,false | false |否 |
| show-header | 是否显示表头 | boolean |true,false | true |否 |
| cell-style | 单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。 | Function({row, column, rowIndex, columnIndex})/Object |-- | -- |否 |
| cell-header-style | 头部单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。 | Function({ column, columnIndex})/Object |-- | -- |否 |
| formatter | colomn =》formatter 必须设置为true,才有作用,进行格式化数据,进行数据的转换 | Function({row, column, rowIndex, columnIndex})/Object |-- | -- |否 |
| border | 是否带有纵向边框 | boolean |true,false | true |否 |
| highlight | 是否要高亮当前行 | boolean |true,false | false |否 |
| show-summary | 是否在表尾显示合计行 | boolean |true,false | false |否 |
| sum-text | 合计行第一列的文本 | String |- | 合计 |否 |
| summary-method | 自定义的合计计算方法 | Function({ columns, data }) |- | - |否 |
| permissionBtn | 是否动态控制按钮的显示隐藏 | Function({ row, renders,index }) |- | - |否 |
| isShowLoadMore | 是否开启上拉加载 | boolean |true,false | false |否 |
| pullUpLoading | 开启上拉加载后的返回函数,接收参数done是函数,done(type),type为空代表还有数据,继续开启上拉加载,type='ok',代表结束上拉加载 | Function(done) |-- | -- |否 |
```
关闭上拉加载的方式1:pullUpLoading((done)=>{
done(type)
})
done 接收参数为 type ,type为空代表还有数据,可以继续加载,无数据的时候传入 'ok'代表结束
```
## table 事件
| 参数 | 说明 | 类型 | 可选值 | 默认值 |是否必须|
| ------ | ------ | ------ |--------------------------| ------ |------ |
| 事件名自定义 | 取决于type类型为operation的 renders参数里面 func 的参数名 | Function | (row,index)=>{} | -- |否 |
| sort-change | 取决于type类型为operation的 renders参数里面 func 的参数名 | Function | (column,model,index)=>{} | -- |否 |
| currentChange | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight属性,this.$refs.table.resetHighlight()清除选中 | Function | (row,index)=>{} | -- |否 |
| toggleRowSelection | 用于多选表格,切换某一行的选中状态,第一个参数代表选中状态,参数二代表选中的对象 | Function | (selected ,array)=>{} | -- |否 |
| toggleAllSelection | 用于多选表格,切换所有行的选中状态 ,第一个参数代表选中状态,参数二代表选中的对象| Function | (selected ,array)=>{} | -- |否 |
| rowClick | 单击某行 ,第一个参数代表选中对象,参数二代表选中的index| Function | (row ,index)=>{} | -- |否 |
| cellClick | 单击单元格 ,当某个单元格被点击时会触发该事件| Function | (row ,index,column)=>{} | -- |否 |
| pullUpLoading | 开启上拉加载后的返回函数,无参数| Function | -- |-- |否 |
```
关闭上拉加载的方式2:this.$refs.zbTable.pullUpCompleteLoading('ok')
接收参数为 type ,type为空代表还有数据,可以继续加载,无数据的时候传入 'ok'代表结束
```
## data 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------ | ------ | ------ | ------ | ------ |
| checked | 是否被勾选 | boolean |true,false | 无 |
## column 属性
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
| ------ | ------ | ------ | ------ | ------ |
| name | 属性值 | string |-- | 无 |
| label | 显示的标题 | string |-- | 无 |
| width | 列的宽度 | number |-- | 100 |
| fixed | 列是否固定在左侧,true 表示固定在左侧 | boolean |true,false | true |
| sorter | 排序,当设置为custom的时候代表自定义排序,不会再触发默认排序,会触发table事件@sort-change,可以通过接口来进行排序 | boolean |true,false,'custom' | false |
| emptyString | 当值为空的时候默认显示的值 | string | | -- |
| filters | 对象过滤的选项,对象格式,对象中的元素需要有 key 和 value 属性。 | Object | {key:value} | -- |
| align | 对齐方式 | String | left/center/right | left |
| type | 为 operation 的时候代表为操作按钮,img的时候代表图片地址,index代表序列号 | string | operation,img,index | -- |
| renders | type 为operation的时候 必传 | Array | {name:'名字',func:"父元素接收事件名",type:"按钮的类型",size:"大小"} | -- |
```
type 为 operation 的时候代表为操作按钮
renders 代表传入的按钮 Array =>[
{
name:'编辑',
class:"", // 添加class
type:'primary',代表按钮的类型 type 为custom的时候自定义按钮 其他类型取决于uniapp buttom组件按钮
size:'mini',代表按钮的大小
func:'edit' // func 代表操作按钮点击的事件名字 父元素接收的事件 父元素 @edit
例如:// <zb-table @edit=""/>
}
]
```
## 示例
```
<zb-table
:show-header="true"
:columns="column"
:stripe="true"
:fit="false"
show-summary
sum-text="合计"
@rowClick="rowClick"
:summary-method="getSummaries"
@toggleRowSelection="toggleRowSelection"
@toggleAllSelection="toggleAllSelection"
:border="true"
@edit="buttonEdit"
@dele="dele"
:data="data"></zb-table>
```
## 数据格式
```
column:[
{ type:'selection', fixed:true,width:50 },
{ name: 'name', label: '姓名',fixed:false,width:80,emptyString:'--' },
{ name: 'age', label: '年纪',sorter:false,align:'right', },
{ name: 'sex', label: '性别',filters:{0:'男',1:'女'}},
{ name: 'img', label: '图片',type:"img" },
{ name: 'address', label: '地址' },
{ name: 'date', label: '日期',sorter:true },
{ name: 'province', label: '省份' },
{ name: 'city', label: '城市' },
{ name: 'zip', label: '邮编' },
{ name: 'operation', type:'operation',label: '操作',renders:[
{
name:'编辑',
func:'edit' // func 代表子元素点击的事件 父元素接收的事件 父元素 @edit
},
{
name:'删除',
type:'warn',
func:"dele"
},
]},
],
data:[
{
date: '2016-05-02',
name: '王小虎1',
province: '上海',
sex:'男',
age:'18',
img:"https://img1.baidu.com/it/u=300787145,1214060415&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500",
city: '普陀区',
address: '上海市普',
zip: 200333
},
{
date: '2016-05-02',
name: '王小虎2',
province: '上海',
sex:'男',
age:'18',
city: '普陀区',
address: '上海市普',
zip: 200333
},
{
date: '2016-05-02',
name: '王小虎3',
province: '上海',
sex:'男',
age:'18',
city: '普陀区',
address: '上海市普',
zip: 200333
},
{
date: '2016-05-02',
name: '王小虎4',
province: '上海',
sex:'男',
age:'18',
city: '普陀区',
address: '上海市普',
zip: 200333
},
{
date: '2016-05-02',
name: '王小虎5',
province: '上海',
sex:'男',
age:'18',
city: '普陀区',
address: '上海市普',
zip: 200333
}
]
```
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment