| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- <template>
- <view class="container">
- <!-- 统计类型切换 -->
- <view class="stat-tabs">
- <view
- class="stat-tab"
- :class="{ active: currentStatType === 'task' }"
- @click="switchStatType('task')"
- >
- 任务统计
- </view>
- <view
- class="stat-tab"
- :class="{ active: currentStatType === 'service' }"
- @click="switchStatType('service')"
- >
- 服务单统计
- </view>
- </view>
-
- <!-- 日期范围和筛选 -->
- <view class="date-filter-bar mb16">
- <view class="date-range" @click="showDatePicker = true">
- <image class="w32 h32" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_time.png" mode=""></image>
- <text class="date-text">{{ dateRangeText }}</text>
- <text class="arrow-down">▼</text>
- </view>
- <view class="filter-btn" @click="showFilter = true">
- <image class="w32 h32" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_select.png" mode=""></image>
- <text>筛选</text>
- </view>
- </view>
- <!-- 内容区域 - 动态显示不同的统计表格 -->
- <template v-if="currentStatType === 'task'">
- <!-- 任务完成统计表格 -->
- <statistics-table
- :summary-title="summaryTitle.task[0]"
- :summary-stats="summaryStats.taskComplete"
- :columns="tableColumns.task"
- :table-data="tableData.taskComplete"
- :loading="loading.task"
- height="600rpx"
- @load-more="loadMore('taskComplete')"
- >
- </statistics-table>
- <!-- 任务创建统计表格 -->
- <statistics-table
- :summary-title="summaryTitle.task[1]"
- :summary-stats="summaryStats.taskCreate"
- :columns="tableColumns.task"
- :table-data="tableData.taskCreate"
- :loading="loading.task"
- height="600rpx"
- @load-more="loadMore('taskCreate')"
- >
- </statistics-table>
- </template>
- <template v-else-if="currentStatType === 'service'">
- <!-- 服务单统计表格 -->
- <statistics-table
- :summary-title="summaryTitle.service[0]"
- :summary-stats="summaryStats.service"
- :columns="tableColumns.service"
- :table-data="tableData.service"
- :loading="loading.service"
- height="600rpx"
- @load-more="loadMore('service')"
- >
- </statistics-table>
- <!-- <statistics-table
- :summary-title="summaryTitle.service[1]"
- :summary-stats="summaryStats.service"
- :columns="tableColumns.service"
- :table-data="tableData.service"
- :loading="loading.service"
- @load-more="loadMore('service')"
- >
- </statistics-table> -->
- </template>
- <!-- 日期选择弹窗 -->
- <view class="date-picker-popup" v-if="showDatePicker" @click="showDatePicker = false">
- <view class="date-picker-content" @click.stop>
- <view class="picker-header">
- <view class="picker-cancel" @click="showDatePicker = false">取消</view>
- <view class="picker-title">选择日期范围</view>
- <view class="picker-confirm" @click="confirmDateRange">确定</view>
- </view>
- <view class="picker-body">
- <view class="date-item">
- <text class="date-label">开始日期</text>
- <picker mode="date" :value="tempDateRange.startDate" @change="onStartDateChange">
- <view class="date-value">{{ tempDateRange.startDate || '请选择' }}</view>
- </picker>
- </view>
- <view class="date-item">
- <text class="date-label">结束日期</text>
- <picker mode="date" :value="tempDateRange.endDate" @change="onEndDateChange">
- <view class="date-value">{{ tempDateRange.endDate || '请选择' }}</view>
- </picker>
- </view>
- </view>
- </view>
- </view>
- <!-- 筛选弹窗 -->
- <view class="filter-popup" v-if="showFilter" @click="closeFilter">
- <view class="filter-content" @click.stop>
- <view class="filter-header">
- <view class="filter-title">筛选</view>
- <image class="filter-close-btn" src="https://ysrw-1395926010.cos.ap-chengdu.myqcloud.com/image/icon_cross.png" @click="closeFilter"></image>
- </view>
- <!-- 根据统计类型显示不同的筛选条件 -->
- <template v-if="currentStatType === 'task'">
- <!-- 任务类型筛选 -->
- <view class="filter-group">
- <view class="group-label">任务类型</view>
- <view class="filter-tags">
- <view class="filter-tag" :class="{ active: tempSelectedTaskType.includes(item.dictValue) }"
- v-for="(item, index) in taskTypeDict" :key="index" @click="toggleTaskType(item.dictValue)">
- {{ item.dictLabel }}
- </view>
- </view>
- </view>
- <!-- 任务状态筛选 -->
- <view class="filter-group">
- <view class="group-label">任务状态</view>
- <view class="filter-tags">
- <view class="filter-tag" :class="{ active: tempSelectedTaskStatus.includes(item.dictValue) }"
- v-for="(item, index) in taskStatusDict" :key="index" @click="toggleTaskStatus(item.dictValue)">
- {{ item.dictLabel }}
- </view>
- </view>
- </view>
- </template>
- <template v-else-if="currentStatType === 'service'">
- <view class="filter-group">
- <view class="group-label">服务单结算状态</view>
- <view class="filter-tags">
- <view class="filter-tag" :class="{ active: tempSelectedSettlementStatus === item.dictValue }"
- v-for="(item, index) in serviceOrderSettlementStatusDict" :key="index" @click="selectSettlementStatus(item.dictValue)">
- {{ item.dictLabel }}
- </view>
- </view>
- </view>
- <view class="filter-group">
- <view class="group-label">服务单状态</view>
- <view class="filter-tags">
- <view class="filter-tag" :class="{ active: tempSelectedServiceStatus === item.dictValue }"
- v-for="(item, index) in serviceOrderAuditStatusDict" :key="index"
- @click="selectServiceStatus(item.dictValue)">
- {{ item.dictLabel }}
- </view>
- </view>
- </view>
- </template>
- <!-- 操作按钮 -->
- <view class="filter-actions">
- <view class="reset-btn" @click="resetFilters">重置</view>
- <view class="confirm-btn" @click="confirmFilters">确定</view>
- </view>
- </view>
- </view>
- </view>
- </template>
- <script>
- import utils from '@/utils/common.js'
- import StatisticsTable from '@/components/StatisticsTable.vue'
- import { getTaskCompleteStats, getTaskCreateStats, getStatisticsSummary } from '@/api/task.js'
- export default {
- components: {
- StatisticsTable
- },
- data() {
- const d = new Date();
- const y = d.getFullYear();
- const m = String(d.getMonth() + 1).padStart(2, '0');
- const dd = String(d.getDate()).padStart(2, '0');
- const todayStr = `${y}-${m}-${dd}`;
- const weekAgo = new Date(d);
- weekAgo.setDate(weekAgo.getDate() - 7);
- const y2 = weekAgo.getFullYear();
- const m2 = String(weekAgo.getMonth() + 1).padStart(2, '0');
- const dd2 = String(weekAgo.getDate()).padStart(2, '0');
- const weekAgoStr = `${y2}-${m2}-${dd2}`;
- return {
- userInfo: uni.getStorageSync("userInfo")||'',
- statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px',
- showDatePicker: false,
- showFilter: false,
- currentStatType: 'task', // 当前统计类型: task-任务统计, service-服务单统计
- // 日期范围
- dateRange: {
- startDate: weekAgoStr,
- endDate: todayStr
- },
- tempDateRange: {
- startDate: weekAgoStr,
- endDate: todayStr
- },
-
-
- // 任务统计筛选
- selectedTaskType: [],
- selectedTaskStatus: [],
- tempSelectedTaskType: [],
- tempSelectedTaskStatus: [],
-
- // 服务单统计筛选
- selectedServiceStatus: '',
- tempSelectedServiceStatus: '',
- selectedSettlementStatus: '',
- tempSelectedSettlementStatus: '',
- serviceOrderAuditStatusDict: [],
- serviceOrderSettlementStatusDict: [],
-
-
- // 统计标题(分开存储)
- summaryTitle: {
- service: [ '汇总统计', '明细统计'],
- task: ['任务完成统计', '任务创建统计']
- },
-
- // 统计数据
- summaryStats: {
- taskComplete: [{
- label: '总积分',
- value:0
- }],
- taskCreate: [{
- label: '总积分',
- value: 0
- }],
- service: [{
- label: '总积分',
- value: 0
- }]
- },
-
- // 表格列定义
- tableColumns: {
- task: [{
- title: '归属',
- key: 'deptName',
- width: '24%'
- },
- {
- title: '类型',
- key: 'taskType',
- width: '12%'
- },
- {
- title: '数量',
- key: 'count',
- width: '10%'
- },
- {
- title: '客户',
- key: 'doctorName',
- width: '24%'
- },{
- title: "业务员",
- key: "companyUserName",
- width: "18%"
- },
- {
- title: '积分',
- key: 'totalPoints',
- width: '12%'
- }],
- service: [{
- title: '归属部门',
- key: 'deptName',
- width: '24%'
- },
- {
- title: '服务单数',
- key: 'serviceOrderCount',
- width: '12%'
- },
- {
- title: '任务数',
- key: 'taskCount',
- width: '10%'
- },
- {
- title: '客服数',
- key: 'companyUserCount',
- width: '12%'
- },
- {
- title: '医生数',
- key: 'doctorCount',
- width: '12%'
- },
- {
- title: '任务金额',
- key: 'taskAmount',
- width: '15%'
- },
- {
- title: '总金额',
- key: 'totalAmount',
- width: '15%'
- }
- ]
- },
-
- // 表格数据
- tableData: {
- taskComplete: [
- ],
- taskCreate: [
- ],
- service: []
- },
- // 分页与加载更多控制
- pageSize: 10,
- page: {
- taskComplete: 1,
- taskCreate: 1
- },
- hasMore: {
- taskComplete: true,
- taskCreate: true
- },
- taskTypeDict: [],//任务类型
- taskStatusDict: [],//任务状态
-
- // 加载状态
- loading: {
- task: false,
- service: false
- }
- }
- },
- computed: {
- dateRangeText() {
- const d = new Date()
- const y = d.getFullYear()
- const m = String(d.getMonth() + 1).padStart(2, '0')
- const dd = String(d.getDate()).padStart(2, '0')
- const today = `${y}-${m}-${dd}`
- const start = this.dateRange && this.dateRange.startDate ? this.dateRange.startDate : today
- const end = this.dateRange && this.dateRange.endDate ? this.dateRange.endDate : today
- return `${start} 至 ${end}`
- }
- },
- watch: {
- showFilter(newVal) {
- if (newVal) {
- // 打开弹窗时,同步临时选择值
- if (this.currentStatType === 'task') {
- this.tempSelectedTaskType = [...this.selectedTaskType]
- this.tempSelectedTaskStatus = [...this.selectedTaskStatus]
- } else {
- this.tempSelectedServiceStatus = this.selectedServiceStatus
- this.tempSelectedSettlementStatus = this.selectedSettlementStatus
- }
- }
- },
- currentStatType(newVal) {
- // 切换统计类型时,重置筛选条件(可选)
- this.resetFilters()
- // 重新加载数据
- if (newVal === 'task') {
- this.loadData()
- } else {
- this.getStatisticsSummary()
- }
- }
- },
- onLoad: async function(options) {
- try {
- this.taskTypeDict = await utils.getDicts("task_type");//任务类型
- this.taskStatusDict = await utils.getDicts("task_status");//任务状态
- this.serviceOrderAuditStatusDict = await utils.getDicts("service_order_audit_status");//服务单状态
- this.serviceOrderSettlementStatusDict = await utils.getDicts("service_order_settlement_status");//服务单结算状态
- } catch (e) {
- console.log('获取字典数据失败:', e)
- }
- this.loadData()
-
- },
- onReachBottom() {
- this.loadMore(this.currentStatType)
- },
- methods: {
- //服务单统计汇总
- getStatisticsSummary(){
- let params = {
- companyId: this.userInfo.companyId,
- deptId: this.userInfo.deptId,
- startTime: this.dateRange.startDate,
- endTime: this.dateRange.endDate,
- auditStatus: String(this.selectedServiceStatus || ''),
- settlementStatus: String(this.selectedSettlementStatus || '')
- }
- getStatisticsSummary(params).then(res => {
- if (res.code === 200) {
- const d = res.data || {}
- const list = Array.isArray(d) ? d : (Array.isArray(d.rows) ? d.rows : [])
- this.tableData.service = list
- const totalAmount = d.totalAmount != null
- ? d.totalAmount
- : list.reduce((sum, cur) => sum + Number(cur.totalAmount || 0), 0)
- this.summaryStats.service = [
- { label: '总金额', value: totalAmount }
- ]
- }
- })
- },
-
- // 构造任务统计公共请求参数
- buildTaskParams(pageNum = 1) {
- const userInfo = uni.getStorageSync('userInfo') || {}
- const params = {
- companyId: userInfo.companyId || 1,
- pageNum,
- pageSize: this.pageSize,
- startDate: this.dateRange.startDate,
- endDate: this.dateRange.endDate
- }
- if (this.selectedTaskType && this.selectedTaskType.length > 0) {
- params.taskTypes = this.selectedTaskType.join(',')
- }
- if (this.selectedTaskStatus && this.selectedTaskStatus.length > 0) {
- params.taskStatuses = this.selectedTaskStatus.join(',')
- }
- return params
- },
-
- // 解析任务统计响应,返回 rows/totalCount/totalPoints
- parseTaskStats(res) {
- const d = (res && res.data) || {}
- const rows = Array.isArray(d.rows) ? d.rows : (res.rows || [])
- const totalCount = (d.totalCount != null) ? d.totalCount : (res.total || rows.length || 0)
- const totalPoints = (d.totalPoints != null)
- ? d.totalPoints
- : rows.reduce((sum, item) => sum + (item.totalPoints || 0), 0)
- const normalized = rows.map(item => ({
- ...item,
- taskType: item.taskType || '无类型'
- }))
- return { rows: normalized, totalCount, totalPoints }
- },
- // 切换统计类型
- switchStatType(type) {
- if (this.currentStatType !== type) {
- this.currentStatType = type
- }
- },
-
- goBack() {
- uni.navigateBack()
- },
-
- onStartDateChange(e) {
- this.tempDateRange.startDate = e.detail.value
- },
-
- onEndDateChange(e) {
- this.tempDateRange.endDate = e.detail.value
- },
-
- confirmDateRange() {
- if (!this.tempDateRange.startDate || !this.tempDateRange.endDate) {
- uni.showToast({
- icon: 'none',
- title: '请选择完整的日期范围'
- })
- return
- }
- if (new Date(this.tempDateRange.startDate) > new Date(this.tempDateRange.endDate)) {
- uni.showToast({
- icon: 'none',
- title: '开始日期不能大于结束日期'
- })
- return
- }
- this.dateRange = {
- ...this.tempDateRange
- }
- this.showDatePicker = false
- if (this.currentStatType === 'task') {
- this.loadData()
- } else {
- this.getStatisticsSummary()
- }
- },
-
- closeFilter() {
- // 关闭弹窗时,恢复临时选择值为当前选择值
- if (this.currentStatType === 'task') {
- this.tempSelectedTaskType = this.selectedTaskType
- this.tempSelectedTaskStatus = this.selectedTaskStatus
- } else {
- this.tempSelectedServiceStatus = this.selectedServiceStatus
- this.tempSelectedSettlementStatus = this.selectedSettlementStatus
- }
- this.showFilter = false
- },
-
- // 任务筛选相关方法
- toggleTaskType(value) {
- const index = this.tempSelectedTaskType.indexOf(value);
- if (index > -1) {
- // 已选中,取消选择
- this.tempSelectedTaskType.splice(index, 1);
- } else {
- // 未选中,添加选择
- this.tempSelectedTaskType.push(value);
- }
- },
-
- toggleTaskStatus(value) {
- const index = this.tempSelectedTaskStatus.indexOf(value);
- if (index > -1) {
- // 已选中,取消选择
- this.tempSelectedTaskStatus.splice(index, 1);
- } else {
- // 未选中,添加选择
- this.tempSelectedTaskStatus.push(value);
- }
- },
-
- // 服务单筛选相关方法
- selectServiceType(value) {
- if (this.tempSelectedServiceType === value) {
- this.tempSelectedServiceType = ''
- } else {
- this.tempSelectedServiceType = value
- }
- },
-
- selectServiceStatus(value) {
- if (this.tempSelectedServiceStatus === value) {
- this.tempSelectedServiceStatus = ''
- } else {
- this.tempSelectedServiceStatus = value
- }
- },
- selectSettlementStatus(value) {
- if (this.tempSelectedSettlementStatus === value) {
- this.tempSelectedSettlementStatus = ''
- } else {
- this.tempSelectedSettlementStatus = value
- }
- },
-
- resetFilters() {
- if (this.currentStatType === 'task') {
- this.tempSelectedTaskType = []
- this.tempSelectedTaskStatus = []
- } else {
- this.tempSelectedServiceStatus = ''
- this.tempSelectedSettlementStatus = ''
- }
- },
-
- confirmFilters() {
- if (this.currentStatType === 'task') {
- this.selectedTaskType = [...this.tempSelectedTaskType]
- this.selectedTaskStatus = [...this.tempSelectedTaskStatus]
- } else {
- this.selectedServiceStatus = this.tempSelectedServiceStatus
- this.selectedSettlementStatus = this.tempSelectedSettlementStatus
- }
- this.showFilter = false
- if (this.currentStatType === 'task') {
- this.loadData()
- } else {
- this.getStatisticsSummary()
- }
- },
-
- async loadData() {
- try {
- uni.showLoading({
- title: '加载中...'
- })
-
- // 根据当前统计类型加载数据
- if (this.currentStatType === 'task') {
- // 加载任务统计数据
- // 获取用户信息
- const userInfo = uni.getStorageSync('userInfo')
-
- // 重置分页
- this.page.taskComplete = 1
- this.page.taskCreate = 1
-
- // 并发获取完成与创建统计
- const params = this.buildTaskParams(1)
- const [completeStatsRes, createStatsRes] = await Promise.all([
- getTaskCompleteStats(params),
- getTaskCreateStats(params)
- ])
-
- // 处理返回的数据
- if (completeStatsRes.code === 200) {
- const comp = this.parseTaskStats(completeStatsRes)
- this.tableData.taskComplete = comp.rows
- this.hasMore.taskComplete = comp.rows.length >= this.pageSize
- this.summaryStats.taskComplete = [
- { label: '总任务数', value: comp.totalCount },
- { label: '总积分', value: comp.totalPoints }
- ]
- }
-
- if (createStatsRes.code === 200) {
- const cre = this.parseTaskStats(createStatsRes)
- this.tableData.taskCreate = cre.rows
- this.hasMore.taskCreate = cre.rows.length >= this.pageSize
- this.summaryStats.taskCreate = [
- { label: '总任务数', value: cre.totalCount },
- { label: '总积分', value: cre.totalPoints }
- ]
- }
-
- uni.hideLoading()
-
- } else {
- // 加载服务单统计数据
- // 模拟数据
- setTimeout(() => {
- uni.hideLoading()
- // 这里可以更新数据
- }, 500)
- }
-
- } catch (e) {
- uni.hideLoading()
- console.error('加载数据失败', e)
- }
- },
-
- async loadMore(which) {
- // 仅处理两个任务表格的加载更多;无更多时拦截
- if (which === 'taskComplete' && !this.hasMore.taskComplete) return
- if (which === 'taskCreate' && !this.hasMore.taskCreate) return
-
- this.loading.task = true
- try {
- if (which === 'taskComplete') {
- const nextPage = this.page.taskComplete + 1
- const res = await getTaskCompleteStats(this.buildTaskParams(nextPage))
- if (res.code === 200) {
- const comp = this.parseTaskStats(res)
- if (comp.rows.length > 0) {
- this.tableData.taskComplete = this.tableData.taskComplete.concat(comp.rows)
- this.page.taskComplete = nextPage
- }
- this.hasMore.taskComplete = comp.rows.length >= this.pageSize
- }
- } else if (which === 'taskCreate') {
- const nextPage2 = this.page.taskCreate + 1
- const res2 = await getTaskCreateStats(this.buildTaskParams(nextPage2))
- if (res2.code === 200) {
- const cre = this.parseTaskStats(res2)
- if (cre.rows.length > 0) {
- this.tableData.taskCreate = this.tableData.taskCreate.concat(cre.rows)
- this.page.taskCreate = nextPage2
- }
- this.hasMore.taskCreate = cre.rows.length >= this.pageSize
- }
- }
- } finally {
- this.loading.task = false
- }
- },
-
- // 去掉本地“更多任务”占位数据与服务单模拟追加,保持真实接口分页
-
- // 根据taskType获取任务类型名称
- getTaskTypeName(taskType) {
- // 任务类型映射
- const taskTypeMap = {
- '1': '医生坐诊',
- '2': '科普讲座',
- '3': '学术讲座',
- '4': '科普文章',
- '5': '科普短视频',
- '6': '科普长视频',
- '7': '空中课堂',
- '8': '用药调研',
- '9': '问卷调研',
- '10': '社群咨询',
- '11': '健康问答'
- }
- return taskTypeMap[taskType] || '未知类型'
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .container {
- min-height: 100vh;
- background: #f7f8fa;
- padding-bottom: 20rpx;
- }
-
- /* 统计类型切换样式 */
- .stat-tabs {
- display: flex;
- background: #fff;
- padding: 24rpx;
-
- .stat-tab {
- flex: 1;
- text-align: center;
- padding: 20rpx 0;
- font-size: 32rpx;
- color: #999;
- position: relative;
-
- &.active {
- color: #333333;
- font-weight: bold;
-
- &::after {
- content: '';
- position: absolute;
- bottom: 0;
- left: 50%;
- transform: translateX(-50%);
- width: 60rpx;
- height: 6rpx;
- background: #388BFF;
- border-radius: 3rpx;
- }
- }
- }
- }
-
- .date-filter-bar {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 24rpx;
- background: #fff;
-
- .date-range {
- display: flex;
- align-items: center;
- gap: 8rpx;
-
- .date-text {
- font-family: PingFang SC, PingFang SC;
- font-weight: 500;
- font-size: 28rpx;
- color: #333333;
- }
-
- .arrow-down {
- font-size: 20rpx;
- color: #333333;
- }
- }
-
- .filter-btn {
- display: flex;
- align-items: center;
- gap: 8rpx;
- font-size: 28rpx;
- color: #999999;
- }
- }
-
- .w32 {
- width: 32rpx;
- }
-
- .h32 {
- height: 32rpx;
- }
-
- .mb16 {
- margin-bottom: 16rpx;
- }
-
- .status-tag {
- padding: 4rpx 12rpx;
- border-radius: 4rpx;
- font-size: 24rpx;
-
- &.uncompleted,
- &.pending {
- background: #FFF3E0;
- color: #FF9800;
- }
-
- &.completed {
- background: #E8F5E9;
- color: #4CAF50;
- }
-
- &.pendingReview {
- background: #E3F2FD;
- color: #2196F3;
- }
-
- &.rejected {
- background: #FFEBEE;
- color: #F44336;
- }
-
- &.processing {
- background: #E3F2FD;
- color: #2196F3;
- }
-
- &.closed,
- &.cancelled {
- background: #F5F5F5;
- color: #9E9E9E;
- }
- }
-
- /* 日期选择弹窗样式 */
- .date-picker-popup {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- z-index: 999;
- display: flex;
- align-items: flex-end;
- }
-
- .date-picker-content {
- width: 100%;
- background: #fff;
- border-radius: 24rpx 24rpx 0 0;
-
- .picker-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 24rpx;
-
- .picker-cancel {
- font-size: 30rpx;
- color: #666;
- }
-
- .picker-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
-
- .picker-confirm {
- font-size: 30rpx;
- color: #388BFF;
- }
- }
-
- .picker-body {
- padding: 24rpx;
-
- .date-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 24rpx 0;
- &:last-child {
- border-bottom: none;
- }
-
- .date-label {
- font-size: 30rpx;
- color: #333;
- }
-
- .date-value {
- font-size: 30rpx;
- color: #388BFF;
- }
- }
- }
- }
-
- /* 筛选弹窗样式 */
- .filter-popup {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- z-index: 999;
- display: flex;
- align-items: flex-end;
- }
-
- .filter-content {
- width: 100%;
- background: #fff;
- border-radius: 24rpx 24rpx 0 0;
- padding: 24rpx;
- max-height: 80vh;
- overflow-y: auto;
-
- .filter-header {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 32rpx;
- position: relative;
-
- .filter-title {
- font-size: 32rpx;
- font-weight: bold;
- color: #333;
- }
-
- .filter-close-btn {
- width: 44rpx;
- height: 44rpx;
- position: absolute;
- right: 0;
- }
- }
-
- .filter-group {
- margin-bottom: 40rpx;
-
- .group-label {
- font-size: 28rpx;
- font-weight: bold;
- color: #333;
- margin-bottom: 20rpx;
- }
-
- .filter-tags {
- display: flex;
- flex-wrap: wrap;
- gap: 20rpx;
-
- .filter-tag {
- padding: 12rpx 24rpx;
- font-size: 28rpx;
- color: #333;
- background: #F7F8FA;
- border-radius: 70rpx;
-
- &.active {
- background: rgba(56, 139, 255, 0.15);
- color: #388BFF;
- }
- }
- }
- }
-
- .filter-actions {
- display: flex;
- gap: 24rpx;
- margin-top: 40rpx;
- padding-top: 24rpx;
- border-top: 1rpx solid #f0f0f0;
-
- .reset-btn,
- .confirm-btn {
- flex: 1;
- height: 88rpx;
- line-height: 88rpx;
- text-align: center;
- border-radius: 200rpx;
- font-size: 28rpx;
- }
-
- .reset-btn {
- background: #fff;
- color: #388BFF;
- border: 2rpx solid #388BFF;
- }
-
- .confirm-btn {
- background: #388BFF;
- color: #fff;
- }
- }
- }
- </style>
|