956 lines
22 KiB
Plaintext
956 lines
22 KiB
Plaintext
<template>
|
|
<view class="incident-report">
|
|
<!-- Header -->
|
|
<view class="header">
|
|
<view class="header-content">
|
|
<text class="header-title">事件报告</text>
|
|
<text class="header-subtitle">记录和跟踪护理事件</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Quick Stats -->
|
|
<view class="stats-section">
|
|
<view class="stats-grid">
|
|
<view class="stat-card urgent">
|
|
<text class="stat-number">{{ stats.urgent_incidents }}</text>
|
|
<text class="stat-label">紧急事件</text>
|
|
<text class="stat-trend">今日新增</text>
|
|
</view>
|
|
<view class="stat-card pending">
|
|
<text class="stat-number">{{ stats.pending_reports }}</text>
|
|
<text class="stat-label">待处理</text>
|
|
<text class="stat-trend">需要跟进</text>
|
|
</view>
|
|
<view class="stat-card resolved">
|
|
<text class="stat-number">{{ stats.resolved_today }}</text>
|
|
<text class="stat-label">今日解决</text>
|
|
<text class="stat-trend">已完成</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- New Incident Button -->
|
|
<view class="new-incident-section">
|
|
<view class="new-incident-btn" @tap="showNewIncidentModal">
|
|
<text class="new-incident-icon">📝</text>
|
|
<text class="new-incident-text">新建事件报告</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- Filter Tabs -->
|
|
<view class="filter-section">
|
|
<scroll-view class="filter-scroll" scroll-x="true">
|
|
<view class="filter-tabs">
|
|
<view v-for="filter in filterOptions" :key="filter.value"
|
|
class="filter-tab" :class="{active: currentFilter === filter.value}"
|
|
@tap="setFilter(filter.value)">
|
|
<text class="filter-text">{{ filter.label }}</text>
|
|
<text v-if="filter.count > 0" class="filter-count">{{ filter.count }}</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
|
|
<!-- Incidents List -->
|
|
<view class="incidents-section">
|
|
<view v-if="filteredIncidents.length === 0" class="empty-state">
|
|
<text class="empty-icon">📋</text>
|
|
<text class="empty-text">暂无事件记录</text>
|
|
<text class="empty-subtitle">点击上方按钮创建新的事件报告</text>
|
|
</view>
|
|
<view v-else class="incidents-list">
|
|
<view v-for="incident in filteredIncidents" :key="incident.id"
|
|
class="incident-card" @tap="viewIncidentDetail(incident)">
|
|
<view class="incident-header">
|
|
<view class="incident-info">
|
|
<text class="incident-title">{{ incident.title }}</text>
|
|
<text class="incident-elder">{{ incident.elder_name }}</text>
|
|
</view>
|
|
<view class="incident-priority" :class="getPriorityClass(incident.priority)">
|
|
<text class="priority-text">{{ getPriorityText(incident.priority) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="incident-content">
|
|
<text class="incident-description">{{ incident.description }}</text>
|
|
</view>
|
|
|
|
<view class="incident-meta">
|
|
<view class="incident-time">
|
|
<text class="time-label">发生时间:</text>
|
|
<text class="time-value">{{ formatDateTime(incident.incident_time) }}</text>
|
|
</view>
|
|
<view class="incident-reporter">
|
|
<text class="reporter-label">报告人:</text>
|
|
<text class="reporter-value">{{ incident.reporter_name }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="incident-footer">
|
|
<view class="incident-status" :class="getStatusClass(incident.status)">
|
|
<text class="status-text">{{ getStatusText(incident.status) }}</text>
|
|
</view>
|
|
<view class="incident-actions">
|
|
<text class="action-time">{{ formatTime(incident.created_at) }}</text>
|
|
<text v-if="incident.status === 'pending'" class="action-follow" @tap.stop="followUpIncident(incident)">跟进</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- New Incident Modal -->
|
|
<view v-if="showModal" class="modal-overlay" @tap="hideModal">
|
|
<view class="modal-content" @tap.stop>
|
|
<view class="modal-header">
|
|
<text class="modal-title">新建事件报告</text>
|
|
<text class="modal-close" @tap="hideModal">✕</text>
|
|
</view>
|
|
|
|
<scroll-view class="modal-body">
|
|
<view class="form-group">
|
|
<text class="form-label">事件标题 *</text>
|
|
<input class="form-input" v-model="newIncident.title" placeholder="请输入事件标题" />
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">相关老人 *</text>
|
|
<picker class="form-picker" mode="selector" :value="elderIndex" :range="elderOptions" range-key="name" @change="onElderChange">
|
|
<view class="picker-display">
|
|
<text class="picker-text">{{ elderOptions[elderIndex]?.name || '请选择老人' }}</text>
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">优先级 *</text>
|
|
<picker class="form-picker" mode="selector" :value="priorityIndex" :range="priorityOptions" @change="onPriorityChange">
|
|
<view class="picker-display">
|
|
<text class="picker-text">{{ priorityOptions[priorityIndex] }}</text>
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">事件类型</text>
|
|
<picker class="form-picker" mode="selector" :value="typeIndex" :range="typeOptions" @change="onTypeChange">
|
|
<view class="picker-display">
|
|
<text class="picker-text">{{ typeOptions[typeIndex] }}</text>
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">发生时间</text>
|
|
<picker class="form-picker" mode="datetime" :value="newIncident.incident_time" @change="onTimeChange">
|
|
<view class="picker-display">
|
|
<text class="picker-text">{{ formatDateTime(newIncident.incident_time) || '选择时间' }}</text>
|
|
<text class="picker-arrow">▼</text>
|
|
</view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">事件描述 *</text>
|
|
<textarea class="form-textarea" v-model="newIncident.description" placeholder="请详细描述事件经过..." />
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">处理措施</text>
|
|
<textarea class="form-textarea" v-model="newIncident.action_taken" placeholder="请描述已采取的处理措施..." />
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="btn btn-cancel" @tap="hideModal">取消</button>
|
|
<button class="btn btn-submit" @tap="submitIncident" :disabled="isSubmitting">
|
|
{{ isSubmitting ? '提交中...' : '提交报告' }}
|
|
</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="uts">
|
|
import { IncidentReport, ElderInfo, IncidentStats } from '../types.uts'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
currentFilter: 'all',
|
|
showModal: false,
|
|
isSubmitting: false,
|
|
elderIndex: 0,
|
|
priorityIndex: 0,
|
|
typeIndex: 0,
|
|
stats: {
|
|
urgent_incidents: 0,
|
|
pending_reports: 0,
|
|
resolved_today: 0
|
|
} as IncidentStats,
|
|
incidents: [] as IncidentReport[],
|
|
elderOptions: [] as ElderInfo[],
|
|
newIncident: {
|
|
title: '',
|
|
elder_id: '',
|
|
priority: 'normal',
|
|
incident_type: 'medical',
|
|
description: '',
|
|
action_taken: '',
|
|
incident_time: new Date().toISOString()
|
|
} as IncidentReport,
|
|
filterOptions: [
|
|
{ label: '全部', value: 'all', count: 0 },
|
|
{ label: '待处理', value: 'pending', count: 0 },
|
|
{ label: '处理中', value: 'in_progress', count: 0 },
|
|
{ label: '已解决', value: 'resolved', count: 0 },
|
|
{ label: '紧急', value: 'urgent', count: 0 }
|
|
],
|
|
priorityOptions: ['普通', '高', '紧急', '危急'],
|
|
typeOptions: ['医疗事件', '安全事件', '行为事件', '设备故障', '其他']
|
|
}
|
|
},
|
|
computed: {
|
|
filteredIncidents(): IncidentReport[] {
|
|
if (this.currentFilter === 'all') {
|
|
return this.incidents
|
|
}
|
|
|
|
if (this.currentFilter === 'urgent') {
|
|
return this.incidents.filter(incident => incident.priority === 'urgent' || incident.priority === 'critical')
|
|
}
|
|
|
|
return this.incidents.filter(incident => incident.status === this.currentFilter)
|
|
}
|
|
},
|
|
onLoad() {
|
|
this.loadIncidentData()
|
|
},
|
|
onShow() {
|
|
this.loadIncidentData()
|
|
},
|
|
methods: {
|
|
async loadIncidentData() {
|
|
try {
|
|
await Promise.all([
|
|
this.loadIncidentStats(),
|
|
this.loadIncidents(),
|
|
this.loadElderOptions()
|
|
])
|
|
this.updateFilterCounts()
|
|
} catch (error) {
|
|
console.error('加载事件数据失败:', error)
|
|
}
|
|
},
|
|
|
|
async loadIncidentStats() {
|
|
const result = await supa.executeAs('incident_stats', {})
|
|
if (result.success && result.data.length > 0) {
|
|
this.stats = result.data[0] as IncidentStats
|
|
}
|
|
},
|
|
|
|
async loadIncidents() {
|
|
const result = await supa.executeAs('incident_reports', {})
|
|
if (result.success) {
|
|
this.incidents = result.data as IncidentReport[]
|
|
}
|
|
},
|
|
|
|
async loadElderOptions() {
|
|
const result = await supa.executeAs('active_elders', {})
|
|
if (result.success) {
|
|
this.elderOptions = result.data as ElderInfo[]
|
|
}
|
|
},
|
|
|
|
updateFilterCounts() {
|
|
this.filterOptions.forEach(filter => {
|
|
if (filter.value === 'all') {
|
|
filter.count = this.incidents.length
|
|
} else if (filter.value === 'urgent') {
|
|
filter.count = this.incidents.filter(incident =>
|
|
incident.priority === 'urgent' || incident.priority === 'critical'
|
|
).length
|
|
} else {
|
|
filter.count = this.incidents.filter(incident => incident.status === filter.value).length
|
|
}
|
|
})
|
|
},
|
|
|
|
setFilter(filter: string) {
|
|
this.currentFilter = filter
|
|
},
|
|
|
|
showNewIncidentModal() {
|
|
this.showModal = true
|
|
this.resetForm()
|
|
},
|
|
|
|
hideModal() {
|
|
this.showModal = false
|
|
},
|
|
|
|
resetForm() {
|
|
this.newIncident = {
|
|
title: '',
|
|
elder_id: '',
|
|
priority: 'normal',
|
|
incident_type: 'medical',
|
|
description: '',
|
|
action_taken: '',
|
|
incident_time: new Date().toISOString()
|
|
} as IncidentReport
|
|
this.elderIndex = 0
|
|
this.priorityIndex = 0
|
|
this.typeIndex = 0
|
|
},
|
|
|
|
onElderChange(e) {
|
|
this.elderIndex = e.detail.value
|
|
if (this.elderOptions[this.elderIndex]) {
|
|
this.newIncident.elder_id = this.elderOptions[this.elderIndex].id
|
|
}
|
|
},
|
|
|
|
onPriorityChange(e) {
|
|
this.priorityIndex = e.detail.value
|
|
const priorityMap = ['normal', 'high', 'urgent', 'critical']
|
|
this.newIncident.priority = priorityMap[e.detail.value]
|
|
},
|
|
|
|
onTypeChange(e) {
|
|
this.typeIndex = e.detail.value
|
|
const typeMap = ['medical', 'safety', 'behavioral', 'equipment', 'other']
|
|
this.newIncident.incident_type = typeMap[e.detail.value]
|
|
},
|
|
|
|
onTimeChange(e) {
|
|
this.newIncident.incident_time = e.detail.value
|
|
},
|
|
|
|
async submitIncident() {
|
|
if (!this.validateForm()) {
|
|
return
|
|
}
|
|
|
|
this.isSubmitting = true
|
|
|
|
try {
|
|
const result = await supa.executeAs('create_incident_report', {
|
|
...this.newIncident,
|
|
status: 'pending'
|
|
})
|
|
|
|
if (result.success) {
|
|
uni.showToast({
|
|
title: '报告提交成功',
|
|
icon: 'success'
|
|
})
|
|
this.hideModal()
|
|
this.loadIncidentData()
|
|
} else {
|
|
throw new Error(result.error || '提交失败')
|
|
}
|
|
} catch (error) {
|
|
console.error('提交事件报告失败:', error)
|
|
uni.showToast({
|
|
title: '提交失败',
|
|
icon: 'error'
|
|
})
|
|
} finally {
|
|
this.isSubmitting = false
|
|
}
|
|
},
|
|
|
|
validateForm(): boolean {
|
|
if (!this.newIncident.title.trim()) {
|
|
uni.showToast({
|
|
title: '请输入事件标题',
|
|
icon: 'error'
|
|
})
|
|
return false
|
|
}
|
|
|
|
if (!this.newIncident.elder_id) {
|
|
uni.showToast({
|
|
title: '请选择相关老人',
|
|
icon: 'error'
|
|
})
|
|
return false
|
|
}
|
|
|
|
if (!this.newIncident.description.trim()) {
|
|
uni.showToast({
|
|
title: '请输入事件描述',
|
|
icon: 'error'
|
|
})
|
|
return false
|
|
}
|
|
|
|
return true
|
|
},
|
|
|
|
async followUpIncident(incident: IncidentReport) {
|
|
try {
|
|
const result = await supa.executeAs('update_incident_status', {
|
|
incident_id: incident.id,
|
|
status: 'in_progress'
|
|
})
|
|
|
|
if (result.success) {
|
|
uni.showToast({
|
|
title: '已开始跟进',
|
|
icon: 'success'
|
|
})
|
|
this.loadIncidents()
|
|
}
|
|
} catch (error) {
|
|
console.error('跟进事件失败:', error)
|
|
uni.showToast({
|
|
title: '操作失败',
|
|
icon: 'error'
|
|
})
|
|
}
|
|
},
|
|
|
|
viewIncidentDetail(incident: IncidentReport) {
|
|
uni.navigateTo({
|
|
url: `/pages/ec/incident/detail?id=${incident.id}`
|
|
})
|
|
},
|
|
|
|
getPriorityClass(priority: string): string {
|
|
const priorityMap = {
|
|
'normal': 'priority-normal',
|
|
'high': 'priority-high',
|
|
'urgent': 'priority-urgent',
|
|
'critical': 'priority-critical'
|
|
}
|
|
return priorityMap[priority] || 'priority-normal'
|
|
},
|
|
|
|
getPriorityText(priority: string): string {
|
|
const priorityMap = {
|
|
'normal': '普通',
|
|
'high': '高',
|
|
'urgent': '紧急',
|
|
'critical': '危急'
|
|
}
|
|
return priorityMap[priority] || '普通'
|
|
},
|
|
|
|
getStatusClass(status: string): string {
|
|
const statusMap = {
|
|
'pending': 'status-pending',
|
|
'in_progress': 'status-progress',
|
|
'resolved': 'status-resolved',
|
|
'closed': 'status-closed'
|
|
}
|
|
return statusMap[status] || 'status-pending'
|
|
},
|
|
|
|
getStatusText(status: string): string {
|
|
const statusMap = {
|
|
'pending': '待处理',
|
|
'in_progress': '处理中',
|
|
'resolved': '已解决',
|
|
'closed': '已关闭'
|
|
}
|
|
return statusMap[status] || '未知'
|
|
},
|
|
|
|
formatTime(timestamp: string): string {
|
|
if (!timestamp) return ''
|
|
|
|
const date = new Date(timestamp)
|
|
const now = new Date()
|
|
const diff = now.getTime() - date.getTime()
|
|
const minutes = Math.floor(diff / (1000 * 60))
|
|
const hours = Math.floor(minutes / 60)
|
|
const days = Math.floor(hours / 24)
|
|
|
|
if (days > 0) {
|
|
return `${days}天前`
|
|
} else if (hours > 0) {
|
|
return `${hours}小时前`
|
|
} else if (minutes > 0) {
|
|
return `${minutes}分钟前`
|
|
} else {
|
|
return '刚刚'
|
|
}
|
|
},
|
|
|
|
formatDateTime(timestamp: string): string {
|
|
if (!timestamp) return ''
|
|
|
|
const date = new Date(timestamp)
|
|
return `${date.getFullYear()}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.incident-report {
|
|
background-color: #f5f5f5;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.header {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
padding: 40rpx 30rpx 30rpx;
|
|
color: white;
|
|
|
|
.header-title {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.header-subtitle {
|
|
font-size: 26rpx;
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
|
|
.stats-section {
|
|
padding: 30rpx;
|
|
}
|
|
|
|
.stats-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr 1fr;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.stat-card {
|
|
background: white;
|
|
padding: 30rpx 20rpx;
|
|
border-radius: 15rpx;
|
|
text-align: center;
|
|
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
|
|
|
|
.stat-number {
|
|
font-size: 48rpx;
|
|
font-weight: bold;
|
|
margin-bottom: 10rpx;
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
margin-bottom: 5rpx;
|
|
}
|
|
|
|
.stat-trend {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
|
|
&.urgent {
|
|
.stat-number {
|
|
color: #ff6b6b;
|
|
}
|
|
}
|
|
|
|
&.pending {
|
|
.stat-number {
|
|
color: #4ecdc4;
|
|
}
|
|
}
|
|
|
|
&.resolved {
|
|
.stat-number {
|
|
color: #45b7d1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.new-incident-section {
|
|
padding: 0 30rpx 30rpx;
|
|
}
|
|
|
|
.new-incident-btn {
|
|
background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%);
|
|
padding: 30rpx;
|
|
border-radius: 15rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 15rpx;
|
|
color: white;
|
|
|
|
.new-incident-icon {
|
|
font-size: 32rpx;
|
|
}
|
|
|
|
.new-incident-text {
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
|
|
.filter-section {
|
|
padding: 0 30rpx;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.filter-scroll {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.filter-tabs {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.filter-tab {
|
|
padding: 20rpx 30rpx;
|
|
background: white;
|
|
border-radius: 25rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10rpx;
|
|
white-space: nowrap;
|
|
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
|
|
|
|
&.active {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
|
|
.filter-count {
|
|
background: rgba(255,255,255,0.3);
|
|
color: white;
|
|
}
|
|
}
|
|
|
|
.filter-text {
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
.filter-count {
|
|
background: #f0f0f0;
|
|
color: #666;
|
|
padding: 5rpx 10rpx;
|
|
border-radius: 12rpx;
|
|
font-size: 20rpx;
|
|
min-width: 30rpx;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.incidents-section {
|
|
padding: 0 30rpx 30rpx;
|
|
}
|
|
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 120rpx 0;
|
|
|
|
.empty-icon {
|
|
font-size: 80rpx;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.empty-text {
|
|
font-size: 32rpx;
|
|
color: #666;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.empty-subtitle {
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.incidents-list {
|
|
.incident-card {
|
|
background: white;
|
|
margin-bottom: 20rpx;
|
|
border-radius: 15rpx;
|
|
padding: 30rpx;
|
|
box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
|
|
}
|
|
}
|
|
|
|
.incident-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
|
|
.incident-info {
|
|
flex: 1;
|
|
|
|
.incident-title {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.incident-elder {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.incident-priority {
|
|
padding: 10rpx 15rpx;
|
|
border-radius: 20rpx;
|
|
font-size: 22rpx;
|
|
|
|
&.priority-normal {
|
|
background: #e3f2fd;
|
|
color: #1976d2;
|
|
}
|
|
|
|
&.priority-high {
|
|
background: #fff3e0;
|
|
color: #f57c00;
|
|
}
|
|
|
|
&.priority-urgent {
|
|
background: #ffebee;
|
|
color: #d32f2f;
|
|
}
|
|
|
|
&.priority-critical {
|
|
background: #f3e5f5;
|
|
color: #7b1fa2;
|
|
}
|
|
}
|
|
|
|
.incident-content {
|
|
margin-bottom: 20rpx;
|
|
|
|
.incident-description {
|
|
font-size: 26rpx;
|
|
color: #555;
|
|
line-height: 1.6;
|
|
}
|
|
}
|
|
|
|
.incident-meta {
|
|
margin-bottom: 20rpx;
|
|
|
|
.incident-time, .incident-reporter {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 10rpx;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
|
|
.time-label, .reporter-label {
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
width: 120rpx;
|
|
}
|
|
|
|
.time-value, .reporter-value {
|
|
font-size: 24rpx;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.incident-footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding-top: 20rpx;
|
|
border-top: 2rpx solid #f0f0f0;
|
|
}
|
|
|
|
.incident-status {
|
|
padding: 8rpx 15rpx;
|
|
border-radius: 15rpx;
|
|
font-size: 22rpx;
|
|
|
|
&.status-pending {
|
|
background: #fff3e0;
|
|
color: #f57c00;
|
|
}
|
|
|
|
&.status-progress {
|
|
background: #e8f5e8;
|
|
color: #388e3c;
|
|
}
|
|
|
|
&.status-resolved {
|
|
background: #e3f2fd;
|
|
color: #1976d2;
|
|
}
|
|
|
|
&.status-closed {
|
|
background: #f5f5f5;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.incident-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20rpx;
|
|
|
|
.action-time {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
|
|
.action-follow {
|
|
font-size: 24rpx;
|
|
color: #667eea;
|
|
padding: 5rpx 15rpx;
|
|
border: 2rpx solid #667eea;
|
|
border-radius: 15rpx;
|
|
}
|
|
}
|
|
|
|
// Modal styles
|
|
.modal-overlay {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0,0,0,0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.modal-content {
|
|
background: white;
|
|
width: 90%;
|
|
max-height: 80vh;
|
|
border-radius: 20rpx;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.modal-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 30rpx;
|
|
border-bottom: 2rpx solid #f0f0f0;
|
|
|
|
.modal-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.modal-close {
|
|
font-size: 40rpx;
|
|
color: #999;
|
|
width: 60rpx;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.modal-body {
|
|
max-height: 60vh;
|
|
padding: 30rpx;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.form-label {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
margin-bottom: 15rpx;
|
|
}
|
|
|
|
.form-input, .form-textarea {
|
|
width: 100%;
|
|
border: 2rpx solid #e1e1e1;
|
|
border-radius: 10rpx;
|
|
padding: 20rpx;
|
|
font-size: 28rpx;
|
|
background: white;
|
|
|
|
&:focus {
|
|
border-color: #667eea;
|
|
}
|
|
}
|
|
|
|
.form-input {
|
|
height: 80rpx;
|
|
}
|
|
|
|
.form-textarea {
|
|
min-height: 150rpx;
|
|
}
|
|
|
|
.form-picker {
|
|
width: 100%;
|
|
border: 2rpx solid #e1e1e1;
|
|
border-radius: 10rpx;
|
|
background: white;
|
|
}
|
|
|
|
.picker-display {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: 80rpx;
|
|
padding: 0 20rpx;
|
|
|
|
.picker-text {
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.picker-arrow {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.modal-footer {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
padding: 30rpx;
|
|
border-top: 2rpx solid #f0f0f0;
|
|
}
|
|
|
|
.btn {
|
|
flex: 1;
|
|
height: 80rpx;
|
|
border-radius: 10rpx;
|
|
font-size: 28rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
&.btn-cancel {
|
|
background: #f5f5f5;
|
|
color: #666;
|
|
border: 2rpx solid #e1e1e1;
|
|
}
|
|
|
|
&.btn-submit {
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
color: white;
|
|
border: none;
|
|
|
|
&:disabled {
|
|
opacity: 0.6;
|
|
}
|
|
}
|
|
}
|
|
</style>
|