@@ -37,43 +37,34 @@
: show -avatar = " activeTab = = = ' all ' "
: show -avatar = " activeTab = = = ' all ' "
@ card -click = " handleCardClick "
@ card -click = " handleCardClick "
> < / ReportCard >
> < / ReportCard >
<!-- 空状态 -- >
< view v-if = "!loading && projectReportList.length === 0" class="empty-state" >
< view v-if = "!loading && projectReportList.length === 0" class="empty-state" >
< image src = "/static/images/empty_lable.png" class = "empty-image" > < / image >
< image src = "/static/images/empty_lable.png" class = "empty-image" > < / image >
< text class = "empty-text" > 暂无报工数据 < / text >
< text class = "empty-text" > 暂无报工数据 < / text >
< / view >
< / view >
< / view >
< / view >
< u-loadmore v-if = "total > 0" :status="loadMoreStatus" @loadmore="loadMore" > < / u -loadmore >
<!-- 加载更多 -- >
< u-loadmore
v-if = "total > 0"
:status = "loadMoreStatus"
@loadmore ="loadMore"
> < / u-loadmore >
< / scroll-view >
< / scroll-view >
< / view >
< / view >
<!-- 圆形新增按钮 -- >
< view class = "fab-button" @click ="handleAdd" >
< view class = "fab-button" @click ="handleAdd" >
< u -icon name = "plus" color = "#fff" size = "30" > < / u-icon >
< u -icon name = "plus" color = "#fff" size = "30" > < / u-icon >
< / view >
< / view >
<!-- 新增弹窗 -- >
< uni-popup ref = "popup" type = "bottom" :mask-click = "false" >
< uni-popup ref = "popup" type = "bottom" :mask-click = "false" >
< view class = "form-popup-content" >
< view class = "form-popup-content" >
< view class = "popup-header" >
< view class = "popup-header" >
< text class = "popup-title" > { { title } } < / text >
< text class = "popup-title" > { { title } } < / text >
< u-icon name = "close" @click ="cancel" size = "40" > < / u-icon >
< u-icon name = "close" @click ="cancel" size = "40" > < / u-icon >
< / view >
< / view >
< scroll-view scroll -y class = "form-content" >
< scroll-view scroll -y class = "form-content" >
< view class = "form-container" >
< view class = "form-container" >
< view class = "form-item" >
< view class = "form-item" >
< view class = "form-label" > 工作地点 < / view >
< view class = "form-label" > 工作地点 < / view >
< u-input v-model = "form.workPlace" placeholder="请输入工作地点" > < / u -input >
< view class = "location-row" >
< u-input v-model = "form.workPlace" placeholder="系统自动获取中" disabled > < / u-input >
< / view >
< view v-if = "form.locationText" class="location-tip" > 已自动获取当前位置 , 无需手动填写 < / view >
< / view >
< / view >
< view class = "form-item" >
< view class = "form-item" >
< view class = "form-label" > 是否出差 < / view >
< view class = "form-label" > 是否出差 < / view >
< u-radio-group v-model = "form.isTrip" >
< u-radio-group v-model = "form.isTrip" >
@@ -81,7 +72,6 @@
< u-radio :name = "0" label = "否" > < / u-radio >
< u-radio :name = "0" label = "否" > < / u-radio >
< / u-radio-group >
< / u-radio-group >
< / view >
< / view >
< view v-if = "form.isTrip === 1" class="form-item" >
< view v-if = "form.isTrip === 1" class="form-item" >
< view class = "form-label" > 国内 / 国外 < / view >
< view class = "form-label" > 国内 / 国外 < / view >
< u-radio-group v-model = "form.workType" >
< u-radio-group v-model = "form.workType" >
@@ -89,43 +79,28 @@
< u-radio :name = "1" label = "国外" > < / u-radio >
< u-radio :name = "1" label = "国外" > < / u-radio >
< / u-radio-group >
< / u-radio-group >
< / view >
< / view >
< view class = "form-item" >
< view class = "form-item" >
< view class = "form-label" > 请选择项目 < / view >
< view class = "form-label" > 请选择项目 < / view >
< oa-project-select
< oa-project-select v-model = "form.projectId" placeholder="请选择项目" > < / oa -project -select >
v-model = "form.projectId"
placeholder = "请选择项目"
> < / oa-project-select >
< / view >
< / view >
< view class = "form-item" >
< view class = "form-item" >
< view class = "form-label" > 报工内容 < / view >
< view class = "form-label" > 报工内容 < / view >
< Quill
< Quill v-model = "form.content" placeholder="请输入报工内容" :height="200" > < / Quill >
v-model = "form.content"
placeholder = "请输入报工内容"
:height = "200"
> < / Quill >
< / view >
< / view >
< view class = "form-item" >
< view class = "form-item" >
< view class = "form-label" > 备注 < / view >
< view class = "form-label" > 备注 < / view >
< u-input v-model = "form.remark" placeholder="请输入备注" > < / u -input >
< u-input v-model = "form.remark" placeholder="请输入备注" > < / u -input >
< / view >
< / view >
< / view >
< / view >
< / scroll-view >
< / scroll-view >
< view class = "popup-footer" >
< view class = "popup-footer" >
< u-button type = "primary" @click ="submitForm" :loading = "buttonLoading" > 确定 < / u-button >
< u-button type = "primary" @click ="submitForm" :loading = "buttonLoading" > 确定 < / u-button >
< u-button @click ="cancel" > 取消 < / u -button >
< u-button @click ="cancel" > 取消 < / u -button >
< / view >
< / view >
< / view >
< / view >
< / uni-popup >
< / uni-popup >
<!-- 报工详情弹窗 -- >
< ReportDetail ref = "reportDetail" :detail = "reportDetail" > < / ReportDetail >
< ReportDetail
ref = "reportDetail"
:detail = "reportDetail"
> < / ReportDetail >
< / view >
< / view >
< / template >
< / template >
@@ -133,487 +108,100 @@
import { listProjectReport , addProjectReport , getProjectReport } from '@/api/oa/projectReport'
import { listProjectReport , addProjectReport , getProjectReport } from '@/api/oa/projectReport'
import { listProject } from '@/api/oa/project'
import { listProject } from '@/api/oa/project'
import { listDept } from '@/api/oa/dept'
import { listDept } from '@/api/oa/dept'
import { getCityByLocation } from '@/api/fad/location'
import ReportCard from '@/components/ReportCard/index.vue'
import ReportCard from '@/components/ReportCard/index.vue'
import ReportDetail from '@/components/ReportDetail/index.vue'
import ReportDetail from '@/components/ReportDetail/index.vue'
import { mapState } from 'vuex'
import { mapState } from 'vuex'
export default {
export default {
components : {
components : { ReportCard , ReportDetail } ,
ReportCard ,
computed : { ... mapState ( 'user' , [ 'selfInfo' ] ) } ,
ReportDetail ,
} ,
computed : {
... mapState ( 'user' , [ 'selfInfo' ] )
} ,
data ( ) {
data ( ) {
return {
return {
// 当前激活的tab
activeTab : 'all' , scrollHeight : 0 , buttonLoading : false , locationLoading : false ,
activeTab : 'all' ,
locationCanEdit : false ,
// 滚动区域高度
cachedLocation : { city : '' , latitude : null , longitude : null , locationText : '' } ,
scrollHeight : 0 ,
loading : true , total : 0 , projectReportList : [ ] , title : '' , projectList : [ ] , deptList : [ ] ,
// 按钮loading
form : { } , loadMoreStatus : 'loadmore' , refreshing : false , reportDetail : { } ,
buttonLoading : false ,
queryParams : { pageNum : 1 , pageSize : 10 } ,
// 遮罩层
rules : { workPlace : [ { required : true , message : '工作地点不能为空' , trigger : 'blur' } ] , projectId : [ { required : true , message : '项目不能为空' , trigger : 'blur' } ] , content : [ { required : true , message : '报工内容不能为空' , trigger : 'blur' } ] , isTrip : [ { required : true , message : '请选择是否出差' , trigger : 'change' } ] , workType : [ { required : true , message : '请选择出差地点' , trigger : 'change' , validator : ( rule , value , callback ) => { if ( this . form . isTrip === 1 && ! value && value !== 0 ) callback ( new Error ( '请选择出差地点' ) ) ; else callback ( ) ; } } ] }
loading : true ,
// 总条数
total : 0 ,
// 项目报工列表数据
projectReportList : [ ] ,
// 弹出层标题
title : "" ,
// 项目列表
projectList : [ ] ,
// 部门列表
deptList : [ ] ,
// 表单参数
form : { } ,
// 加载更多状态
loadMoreStatus : 'loadmore' ,
// 下拉刷新状态
refreshing : false ,
// 报工详情数据
reportDetail : { } ,
// 分页参数
queryParams : {
pageNum : 1 ,
pageSize : 10
} ,
// 表单校验规则
rules : {
workPlace : [
{ required : true , message : "工作地点不能为空" , trigger : "blur" }
] ,
projectId : [
{ required : true , message : "项目不能为空" , trigger : "blur" }
] ,
content : [
{ required : true , message : "报工内容不能为空" , trigger : "blur" }
] ,
isTrip : [
{ required : true , message : '请选择是否出差' , trigger : 'change' }
] ,
workType : [
{
required : true ,
message : '请选择出差地点' ,
trigger : 'change' ,
validator : ( rule , value , callback ) => {
if ( this . form . isTrip === 1 && ! value && value !== 0 ) {
callback ( new Error ( '请选择出差地点' ) ) ;
} else {
callback ( ) ;
}
}
}
]
}
}
}
} ,
} ,
onLoad ( ) {
onLoad ( ) {
this . calculateScrollHeight ( ) ;
this . calculateScrollHeight ( ) ;
this . getLis t( ) ;
this . checkLocationPermissionAndIni t( ) ;
} ,
onReady ( ) {
// 页面渲染完成后重新计算高度
this . calculateScrollHeight ( ) ;
} ,
} ,
onReady ( ) { this . calculateScrollHeight ( ) ; } ,
methods : {
methods : {
// 计算滚动区域高度
calculateScrollHeight ( ) { const systemInfo = uni . getSystemInfoSync ( ) ; this . scrollHeight = systemInfo . windowHeight - 100 - 40 + 80 ; } ,
calculateScrollHeight ( ) {
switchTab ( tab ) { if ( this . activeTab === tab ) return ; this . activeTab = tab ; this . queryParams . pageNum = 1 ; this . projectReportList = [ ] ; this . getList ( ) ; } ,
const systemInfo = uni . getSystemInfoSync ( ) ;
onRefresh ( ) { this . refreshing = true ; this . queryParams . pageNum = 1 ; this . getList ( ) . finally ( ( ) => { this . refreshing = false ; } ) ; } ,
const tabHeight = 100 ; // tab高度
checkLocationPermissionAndInit ( ) {
const containerPadd ing = 40 ; // 容器padding
if ( typeof uni . getSett ing != = 'function' ) {
// 悬浮按钮是固定定位,不需要预留空间,让卡片列表到达底部
this . getList ( ) ;
// 我也不知道为什么要 + 80, 不然滚动高度下面一大片空白,这个不太好调试
this . getCurrentLocation ( true ) ;
this . scrollHeight = systemInfo . windowHeight - tabHeight - containerPadding + 80 ;
return ;
} ,
}
uni . getSetting ( {
// 切换tab
success : ( settingRes ) => {
switchTab ( tab ) {
const auth = settingRes . authSetting || { } ;
if ( this . activeTab === tab ) return ;
if ( auth [ 'scope.userLocation' ] ) {
this . activeTab = tab ;
this . getList ( ) ;
this . queryParams . pageNum = 1 ;
this . getCurrentLocation ( true ) ;
this . projectReportList = [ ] ;
return ;
this . getList ( ) ;
} ,
// 下拉刷新
onRefresh ( ) {
this . refreshing = true ;
this . queryParams . pageNum = 1 ;
this . getList ( ) . finally ( ( ) => {
this . refreshing = false ;
} ) ;
} ,
// 获取项目列表
getProjectList ( ) {
listProject ( { pageNum : 1 , pageSize : 9999 } ) . then ( res => {
const rawData = res . rows || [ ] ;
// 按照 uni-data-select 的标准格式处理数据
this . projectList = rawData . map ( item => ( {
value : item . projectId ,
text : item . projectName || '未命名项目' ,
// 保留原始数据用于提交
projectId : item . projectId ,
projectName : item . projectName || '未命名项目' ,
projectNum : item . projectNum ,
projectCode : item . projectCode
} ) ) ;
console . log ( '处理后的项目列表数据:' , this . projectList ) ;
// 检查数据结构
if ( this . projectList . length > 0 ) {
console . log ( '第一个项目数据:' , this . projectList [ 0 ] ) ;
}
} ) . catch ( err => {
console . error ( '获取项目列表失败:' , err ) ;
uni . showToast ( {
title : '获取项目列表失败' ,
icon : 'none'
} ) ;
} ) ;
} ,
// 获取部门列表
getDeptList ( ) {
listDept ( ) . then ( res => {
this . deptList = res . data || [ ] ;
} ) . catch ( err => {
console . error ( '获取部门列表失败:' , err ) ;
} ) ;
} ,
// 查询项目报工列表
getList ( ) {
return new Promise ( ( resolve , reject ) => {
this . loading = true ;
// 根据当前tab设置查询参数
const params = {
... this . queryParams
} ;
// 如果是我的报工, 添加用户ID过滤
if ( this . activeTab === 'my' ) {
// 使用当前登录用户的ID
const oaId = uni . getStorageSync ( 'oaId' ) ;
if ( oaId ) {
params . userId = oaId ;
}
}
}
uni . showModal ( {
title : '需要定位权限' ,
listProjectReport ( params ) . then ( response => {
content : '报工页面必须先开启定位权限才能进入。' ,
if ( this . queryParams . pageNum === 1 ) {
confirmText : '去设置' ,
this . projectReportList = response . rows || [ ] ;
cancelText : '返回' ,
} else {
success : ( res ) => {
this . projectReportList = [ ... this . projectReportList , ... ( response . rows || [ ] ) ] ;
if ( res . confirm && typeof uni . openSetting === 'function' ) {
}
uni . openSetting ( {
this . total = response . total || 0 ;
success : ( openRes ) => {
this . loading = false ;
if ( openRes . authSetting && openRes . authSetting [ 'scope.userLocation' ] ) {
this . getList ( ) ;
// 更新加载更多状态
this . getCurrentLocation ( true ) ;
if ( this . queryParams . pageNum > 1 ) {
} else {
this . loadMoreStatus = 'loadmore' ;
uni . navigateBack ( ) ;
}
}
} ,
this . getProjectList ( ) ;
fail : ( ) => uni . navigateBack ( )
// this.getDeptList();
} ) ;
resolve ( response ) ;
} else {
} ) . catch ( err => {
uni . navigateBack ( ) ;
console . error ( '获取报工列表失败:' , err ) ;
}
this . loading = false ;
}
this . loadMoreStatus = 'loadmore' ;
uni . showToast ( {
title : '获取数据失败' ,
icon : 'none'
} ) ;
} ) ;
reject ( err ) ;
} ,
} ) ;
fail : ( ) => {
uni . navigateBack ( ) ;
}
} ) ;
} ) ;
} ,
} ,
getProjectList ( ) { listProject ( { pageNum : 1 , pageSize : 9999 } ) . then ( res => { const rawData = res . rows || [ ] ; this . projectList = rawData . map ( item => ( { value : item . projectId , text : item . projectName || '未命名项目' , projectId : item . projectId , projectName : item . projectName || '未命名项目' , projectNum : item . projectNum , projectCode : item . projectCode } ) ) ; } ) . catch ( ( ) => { } ) ; } ,
// 新增
getDeptList ( ) { listDept ( ) . then ( res => { this . deptList = res . data || [ ] ; } ) . catch ( ( ) => { } ) ; } ,
handleAdd ( ) {
getList ( ) { return new Promise ( ( resolve , reject ) => { this . loading = true ; const params = { ... this . queryParams } ; if ( this . activeTab === 'my' ) { const oaId = uni . getStorageSync ( 'oaId' ) ; if ( oaId ) params . userId = oaId ; } listProjectReport ( params ) . then ( response => { this . projectReportList = this . queryParams . pageNum === 1 ? ( response . rows || [ ] ) : [ ... this . projectReportList , ... ( response . rows || [ ] ) ] ; this . total = response . total || 0 ; this . loading = false ; if ( this . queryParams . pageNum > 1 ) this . loadMoreStatus = 'loadmore' ; this . getProjectList ( ) ; resolve ( response ) ; } ) . catch ( err => { this . loading = false ; this . loadMoreStatus = 'loadmore' ; uni . showToast ( { title : '获取数据失败' , icon : 'none' } ) ; reject ( err ) ; } ) ; } ) ; } ,
this . reset ( ) ;
handleAdd ( ) { this . reset ( ) ; this . title = '添加项目报工' ; if ( this . cachedLocation . city ) { this . form . city = this . cachedLocation . city ; this . form . latitude = this . cachedLocation . latitude ; this . form . longitude = this . cachedLocation . longitude ; this . form . locationText = this . cachedLocation . locationText ; this . form . workPlace = this . cachedLocation . city ; this . locationCanEdit = false ; } else { this . locationCanEdit = true ; } this . $refs . popup . open ( ) ; } ,
this . title = "添加项目报工" ;
handleCardClick ( item ) { this . getReportDetail ( item . reportId ) ; } ,
this . $refs . popup . open ( ) ;
getReportDetail ( reportId ) { this . $refs . reportDetail . open ( ) ; getProjectReport ( reportId ) . then ( response => { this . reportDetail = response . data || response || { } ; } ) . catch ( ( ) => { uni . showToast ( { title : '获取详情失败' , icon : 'none' } ) ; this . $refs . reportDetail . close ( ) ; } ) ; } ,
} ,
submitForm ( ) { if ( ! this . form . workPlace ) { uni . showToast ( { title : '工作地点不能为空' , icon : 'none' } ) ; return ; } if ( this . form . isTrip === undefined ) { uni . showToast ( { title : '请选择是否出差' , icon : 'none' } ) ; return ; } if ( this . form . isTrip === 1 && this . form . workType === undefined ) { uni . showToast ( { title : '请选择出差地点' , icon : 'none' } ) ; return ; } if ( ! this . form . projectId ) { uni . showToast ( { title : '项目不能为空' , icon : 'none' } ) ; return ; } if ( ! this . form . content ) { uni . showToast ( { title : '报工内容不能为空' , icon : 'none' } ) ; return ; } this . buttonLoading = true ; const selectedProject = this . projectList . find ( p => p . value === this . form . projectId ) ; const submitData = { ... this . form , projectName : selectedProject ? . projectName || '' , projectNum : selectedProject ? . projectNum || '' , projectCode : selectedProject ? . projectCode || null , locationText : this . form . locationText || '' } ; addProjectReport ( submitData ) . then ( ( ) => { this . buttonLoading = false ; uni . showToast ( { title : '新增成功' , icon : 'success' } ) ; this . $refs . popup . close ( ) ; this . getList ( ) ; } ) . catch ( ( ) => { this . buttonLoading = false ; uni . showToast ( { title : '新增失败' , icon : 'none' } ) ; } ) ; } ,
cancel ( ) { this . $refs . popup . close ( ) ; this . reset ( ) ; } ,
// 卡片点击事件
getCurrentLocation ( silent = false ) { if ( this . cachedLocation . city && this . cachedLocation . latitude && this . cachedLocation . longitude ) return Promise . resolve ( this . cachedLocation ) ; if ( this . locationLoading ) return Promise . resolve ( null ) ; this . locationLoading = true ; if ( typeof uni . authorize !== 'function' ) return this . requestLocation ( silent ) ; uni . authorize ( { scope : 'scope.userLocation' , success : ( ) => { this . requestLocation ( silent ) ; } , fail : ( ) => { this . locationLoading = false ; this . locationCanEdit = true ; if ( ! silent ) { uni . showModal ( { title : '需要定位权限' , content : '请先授权定位权限后再获取当前位置。' , confirmText : '去设置' , cancelText : '取消' , success : ( res ) => { if ( res . confirm && typeof uni . openSetting === 'function' ) { uni . openSetting ( { success : ( ) => { this . requestLocation ( silent ) ; } } ) ; } } } ) ; } } } ) ; } ,
handleCardClick ( item ) {
requestLocation ( silent = false ) { if ( typeof uni . getLocation !== 'function' ) { this . locationLoading = false ; this . locationCanEdit = true ; return Promise . resolve ( null ) ; } return new Promise ( ( resolve ) => { uni . getLocation ( { type : 'wgs84' , isHighAccuracy : true , highAccuracyExpireTime : 3000 , success : ( res ) => { this . locationLoading = false ; this . locationCanEdit = false ; this . form . latitude = res . latitude ; this . form . longitude = res . longitude ; this . form . locationText = ` 纬度: ${ res . latitude } , 经度: ${ res . longitude } ` ; this . form . workPlace = this . form . locationText ; this . fetchCityByLocation ( res . latitude , res . longitude , silent ) . then ( resolve ) ; } , fail : ( err ) => { this . locationLoading = false ; this . locationCanEdit = true ; console . error ( '获取位置失败:' , err ) ; if ( ! silent ) uni . showToast ( { title : '获取位置失败' , icon : 'none' } ) ; resolve ( null ) ; } } ) ; } ) ; } ,
console . log ( '点击了报工卡片:' , item ) ;
fetchCityByLocation ( latitude , longitude , silent = false ) { return getCityByLocation ( latitude , longitude ) . then ( res => { const city = res ? . msg || res ? . data || '' ; if ( city ) { this . cachedLocation = { city , latitude , longitude , locationText : ` 城市: ${ city } ` } ; this . form . city = city ; this . form . workPlace = ` 城市: ${ city } ` ; this . form . locationText = ` 城市: ${ city } ` ; this . locationCanEdit = false ; return city ; } this . locationCanEdit = true ; if ( ! silent ) { this . form . workPlace = ` 纬度: ${ latitude } , 经度: ${ longitude } ` ; this . form . locationText = this . form . workPlace ; uni . showToast ( { title : '已获取定位,但未识别到城市' , icon : 'none' } ) ; } return '' ; } ) . catch ( ( ) => { this . locationCanEdit = true ; if ( ! silent ) { this . form . workPlace = ` 纬度: ${ latitude } , 经度: ${ longitude } ` ; this . form . locationText = this . form . workPlace ; uni . showToast ( { title : '城市解析失败' , icon : 'none' } ) ; } return '' ; } ) ; } ,
// 获取报工详情
reset ( ) { this . form = { workPlace : '' , locationText : '' , city : '' , latitude : null , longitude : null , projectId : null , content : '' , remark : '' , isTrip : undefined , workType : undefined } ; this . locationCanEdit = false ; } ,
this . ge tReportDetail ( item . reportId ) ;
loadMore ( ) { if ( this . projec tReportList . length >= this . total ) { this . loadMoreStatus = 'nomore' ; return ; } this . queryParams . pageNum ++ ; this . loadMoreStatus = 'loading' ; this . getList ( ) ; }
} ,
// 获取报工详情
getReportDetail ( reportId ) {
// 先打开弹窗显示加载状态
this . $refs . reportDetail . open ( ) ;
getProjectReport ( reportId ) . then ( response => {
// 根据API返回的数据结构处理
this . reportDetail = response . data || response || { } ;
} ) . catch ( err => {
console . error ( '获取报工详情失败:' , err ) ;
uni . showToast ( {
title : '获取详情失败' ,
icon : 'none'
} ) ;
// 关闭弹窗
this . $refs . reportDetail . close ( ) ;
} ) ;
} ,
// 提交表单
submitForm ( ) {
// 手动验证表单
if ( ! this . form . workPlace ) {
uni . showToast ( {
title : '工作地点不能为空' ,
icon : 'none'
} ) ;
return ;
}
if ( this . form . isTrip === undefined ) {
uni . showToast ( {
title : '请选择是否出差' ,
icon : 'none'
} ) ;
return ;
}
if ( this . form . isTrip === 1 && this . form . workType === undefined ) {
uni . showToast ( {
title : '请选择出差地点' ,
icon : 'none'
} ) ;
return ;
}
if ( ! this . form . projectId ) {
uni . showToast ( {
title : '项目不能为空' ,
icon : 'none'
} ) ;
return ;
}
if ( ! this . form . content ) {
uni . showToast ( {
title : '报工内容不能为空' ,
icon : 'none'
} ) ;
return ;
}
// 验证通过,提交表单
this . buttonLoading = true ;
// 获取选中的项目信息
const selectedProject = this . projectList . find ( p => p . value === this . form . projectId ) ;
const submitData = {
... this . form ,
projectName : selectedProject ? . projectName || '' ,
projectNum : selectedProject ? . projectNum || '' ,
projectCode : selectedProject ? . projectCode || null
} ;
addProjectReport ( submitData ) . then ( response => {
this . buttonLoading = false ;
uni . showToast ( {
title : '新增成功' ,
icon : 'success'
} ) ;
this . $refs . popup . close ( ) ;
this . getList ( ) ; // 重新获取列表
} ) . catch ( err => {
this . buttonLoading = false ;
console . error ( '新增失败:' , err ) ;
uni . showToast ( {
title : '新增失败' ,
icon : 'none'
} ) ;
} ) ;
} ,
// 取消
cancel ( ) {
this . $refs . popup . close ( ) ;
this . reset ( ) ;
} ,
// 重置表单
reset ( ) {
this . form = {
workPlace : '' ,
projectId : null ,
content : '' ,
remark : '' ,
isTrip : undefined ,
workType : undefined
} ;
} ,
// 加载更多
loadMore ( ) {
if ( this . projectReportList . length >= this . total ) {
this . loadMoreStatus = 'nomore' ;
return ;
}
this . queryParams . pageNum ++ ;
this . loadMoreStatus = 'loading' ;
this . getList ( ) ;
} ,
}
}
}
}
< / script >
< / script >
< style lang = "scss" scoped >
< style lang = "scss" scoped >
. container {
. container { background - color : # f5f5f5 ; height : 100 vh ; display : flex ; flex - direction : column ; }
background - color : # f5f5f5 ;
. tab - container { display : flex ; background - color : # fff ; padding : 0 20 rpx ; border - bottom : 1 rpx solid # e9ecef ; . tab - item { flex : 1 ; height : 80 rpx ; display : flex ; align - items : center ; justify - content : center ; font - size : 28 rpx ; color : # 666 ; position : relative ; & . active { color : # 007 bff ; font - weight : 500 ; & : : after { content : '' ; position : absolute ; bottom : 0 ; left : 50 % ; transform : translateX ( - 50 % ) ; width : 60 rpx ; height : 4 rpx ; background - color : # 007 bff ; border - radius : 2 rpx ; } } } }
height : 100 vh ;
. card - list - container { flex : 1 ; padding : 20 rpx ; overflow : hidden ; }
display : flex ;
. card - scroll { width : 100 % ; height : 100 % ; }
flex - direction : column ;
. empty - state { display : flex ; flex - direction : column ; align - items : center ; justify - content : center ; padding : 100 rpx 0 ; . empty - image { width : 200 rpx ; height : 200 rpx ; margin - bottom : 30 rpx ; opacity : 0.6 ; } . empty - text { font - size : 28 rpx ; color : # 999 ; } }
}
. form - popup - content { background - color : # fff ; border - radius : 20 rpx 20 rpx 0 0 ; overflow : hidden ; width : 100 % ; max - height : 80 vh ; display : flex ; flex - direction : column ; box - sizing : border - box ; . popup - header { display : flex ; justify - content : space - between ; align - items : center ; padding : 30 rpx ; border - bottom : 1 rpx solid # e9ecef ; . popup - title { font - size : 32 rpx ; font - weight : bold ; } } . form - content { padding : 30 rpx ; flex : 1 ; overflow - y : auto ; box - sizing : border - box ; } . form - container { box - sizing : border - box ; . form - item { margin - bottom : 40 rpx ; box - sizing : border - box ; . form - label { font - size : 28 rpx ; color : # 333 ; margin - bottom : 20 rpx ; font - weight : 500 ; } . location - row { display : flex ; gap : 16 rpx ; align - items : center ; } . location - tip { font - size : 24 rpx ; color : # 999 ; margin - top : 12 rpx ; line - height : 1.4 ; } } } . popup - footer { display : flex ; justify - content : center ; gap : 20 rpx ; padding : 30 rpx ; border - top : 1 rpx solid # e9ecef ; } }
. fab - button { position : fixed ; bottom : 20 rpx ; right : 20 rpx ; width : 100 rpx ; height : 100 rpx ; border - radius : 50 % ; background - color : # 007 bff ; display : flex ; align - items : center ; justify - content : center ; box - shadow : 0 2 rpx 10 rpx rgba ( 0 , 0 , 0 , 0.1 ) ; padding : 20 rpx ; z - index : 999 ; }
. tab - container {
display : flex ;
background - color : # fff ;
padding : 0 20 rpx ;
border - bottom : 1 rpx solid # e9ecef ;
. tab - item {
flex : 1 ;
height : 80 rpx ;
display : flex ;
align - items : center ;
justify - content : center ;
font - size : 28 rpx ;
color : # 666 ;
position : relative ;
& . active {
color : # 007 bff ;
font - weight : 500 ;
& : : after {
content : '' ;
position : absolute ;
bottom : 0 ;
left : 50 % ;
transform : translateX ( - 50 % ) ;
width : 60 rpx ;
height : 4 rpx ;
background - color : # 007 bff ;
border - radius : 2 rpx ;
}
}
}
}
. card - list - container {
flex : 1 ;
padding : 20 rpx ;
overflow : hidden ;
}
. card - scroll {
width : 100 % ;
height : 100 % ;
}
. empty - state {
display : flex ;
flex - direction : column ;
align - items : center ;
justify - content : center ;
padding : 100 rpx 0 ;
. empty - image {
width : 200 rpx ;
height : 200 rpx ;
margin - bottom : 30 rpx ;
opacity : 0.6 ;
}
. empty - text {
font - size : 28 rpx ;
color : # 999 ;
}
}
. form - popup - content {
background - color : # fff ;
border - radius : 20 rpx 20 rpx 0 0 ;
overflow : hidden ;
width : 100 % ;
max - height : 80 vh ;
display : flex ;
flex - direction : column ;
box - sizing : border - box ;
. popup - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
padding : 30 rpx ;
border - bottom : 1 rpx solid # e9ecef ;
. popup - title {
font - size : 32 rpx ;
font - weight : bold ;
}
}
. form - content {
padding : 30 rpx ;
flex : 1 ;
overflow - y : auto ;
box - sizing : border - box ;
}
. form - container {
box - sizing : border - box ;
. form - item {
margin - bottom : 40 rpx ;
box - sizing : border - box ;
. form - label {
font - size : 28 rpx ;
color : # 333 ;
margin - bottom : 20 rpx ;
font - weight : 500 ;
}
}
}
. popup - footer {
display : flex ;
justify - content : center ;
gap : 20 rpx ;
padding : 30 rpx ;
border - top : 1 rpx solid # e9ecef ;
}
}
. fab - button {
position : fixed ;
bottom : 20 rpx ;
right : 20 rpx ;
width : 100 rpx ;
height : 100 rpx ;
border - radius : 50 % ;
background - color : # 007 bff ;
display : flex ;
align - items : center ;
justify - content : center ;
box - shadow : 0 2 rpx 10 rpx rgba ( 0 , 0 , 0 , 0.1 ) ;
padding : 20 rpx ;
z - index : 999 ;
}
< / style >
< / style >