Przeglądaj źródła

feat(任务详情): 新增竞价和周报组件并完善详情页功能

- 添加竞价信息组件展示价格明细和油站策略
- 新增周报信息组件显示站点运营数据
- 扩展任务详情页处理信息展示和图片预览功能
- 优化页面布局和样式
weieryang 2 miesięcy temu
rodzic
commit
f38de9ea4d

+ 153 - 0
apps/web-ele/src/views/schedule/detail/components/bidding.vue

@@ -0,0 +1,153 @@
1
+<script setup lang="ts">
2
+import type { VxeGridProps } from '#/adapter/vxe-table';
3
+
4
+import { useVbenVxeGrid } from '#/adapter/vxe-table';
5
+
6
+import { 
7
+  priceDetailColumns, 
8
+  priceDetailData, 
9
+  stationStrategyColumns, 
10
+  stationStrategyData 
11
+} from './config-data';
12
+
13
+// 价格明细表格配置
14
+const priceDetailGridOptions: VxeGridProps = {
15
+  columns: priceDetailColumns,
16
+  data: priceDetailData,
17
+  border: true,
18
+  showHeaderOverflow: true,
19
+  showOverflow: true,
20
+  size: 'medium',
21
+  height: 'auto',
22
+  // toolbarConfig: {
23
+  //   custom: true,
24
+  //   refresh: false,
25
+  //   zoom: false,
26
+  // },
27
+  proxyConfig: {
28
+    autoLoad: false,
29
+  },
30
+};
31
+
32
+// 油站策略表格配置
33
+const stationStrategyGridOptions: VxeGridProps = {
34
+  columns: stationStrategyColumns,
35
+  data: stationStrategyData,
36
+  border: true,
37
+  showHeaderOverflow: true,
38
+  showOverflow: true,
39
+  size: 'medium',
40
+  height: 'auto',
41
+  // toolbarConfig: {
42
+  //   custom: true,
43
+  //   refresh: false,
44
+  //   zoom: false,
45
+  // },
46
+  proxyConfig: {
47
+    autoLoad: false,
48
+  },
49
+};
50
+
51
+// 创建价格明细表格
52
+const [PriceDetailTable] = useVbenVxeGrid({
53
+  gridOptions: priceDetailGridOptions,
54
+});
55
+
56
+// 创建油站策略表格
57
+const [StationStrategyTable] = useVbenVxeGrid({
58
+  gridOptions: stationStrategyGridOptions,
59
+});
60
+</script>
61
+
62
+<template>
63
+  <div class="task-detail">
64
+    <!-- 页面标题和操作区 -->
65
+    <div class="task-header">
66
+      <div class="left">
67
+        <h3>我方油价:未来路加油站</h3>
68
+        <div class="price-survey-info">
69
+          <span class="survey-date">调查时间:2025-10-29</span>
70
+        </div>
71
+      </div>
72
+      <div class="right">
73
+        <el-button type="primary">打印</el-button>
74
+      </div>
75
+    </div>
76
+
77
+    <!-- 价格明细表格 -->
78
+    <div class="table-section">
79
+      <h4>价格明细:</h4>
80
+      <PriceDetailTable />
81
+    </div>
82
+
83
+    <!-- 油站策略表格 -->
84
+    <div class="table-section">
85
+      <h4>油站策略:</h4>
86
+      <StationStrategyTable />
87
+    </div>
88
+  </div>
89
+</template>
90
+
91
+<style scoped>
92
+.task-detail {
93
+  /* padding: 20px; */
94
+  /* background-color: #fff;
95
+  border-radius: 8px;
96
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
97
+}
98
+
99
+.task-header {
100
+  display: flex;
101
+  justify-content: space-between;
102
+  align-items: flex-start;
103
+  margin-bottom: 20px;
104
+  padding-bottom: 15px;
105
+  border-bottom: 1px solid #e8e8e8;
106
+}
107
+
108
+.task-header .left h3 {
109
+  margin: 0 0 10px 0;
110
+  font-size: 18px;
111
+  color: #333;
112
+}
113
+
114
+.price-survey-info {
115
+  display: flex;
116
+  gap: 20px;
117
+  font-size: 14px;
118
+  color: #666;
119
+}
120
+
121
+.task-header .right {
122
+  display: flex;
123
+  gap: 10px;
124
+}
125
+
126
+.table-section {
127
+  margin-bottom: 30px;
128
+}
129
+
130
+.table-section h4 {
131
+  margin: 0 0 15px 0;
132
+  font-size: 16px;
133
+  color: #333;
134
+  font-weight: 500;
135
+}
136
+
137
+:deep(.vxe-grid) {
138
+  margin-bottom: 0;
139
+}
140
+
141
+:deep(.vxe-table--border) {
142
+  border-color: #e8e8e8;
143
+}
144
+
145
+:deep(.vxe-header--column) {
146
+  background-color: #fafafa;
147
+  font-weight: 500;
148
+}
149
+
150
+:deep(.vxe-cell) {
151
+  padding: 8px 12px;
152
+}
153
+</style>

+ 135 - 0
apps/web-ele/src/views/schedule/detail/components/config-data.tsx

@@ -0,0 +1,135 @@
1
+import type { VxeGridProps } from '#/adapter/vxe-table';
2
+
3
+// 价格明细表格列配置
4
+export const priceDetailColumns: VxeGridProps['columns'] = [
5
+  { field: 'oilType', title: '油品', width: 100, align: 'center' },
6
+  { field: 'weilai0', title: '未来路加油站', width: 150, align: 'center' },
7
+  { field: 'dongming0', title: '东明石化海源加油站', width: 180, align: 'center' },
8
+  { field: 'zhongshihua0', title: '中石化东站路加油站', width: 180, align: 'center' },
9
+  { field: 'dashiqiao0', title: '大石桥石化麟瑞加油站', width: 180, align: 'center' },
10
+  { field: 'weilai1', title: '未来路加油站', width: 150, align: 'center' },
11
+  { field: 'dongming1', title: '东明石化海源加油站', width: 180, align: 'center' },
12
+  { field: 'zhongshihua1', title: '中石化东站路加油站', width: 180, align: 'center' },
13
+  { field: 'dashiqiao1', title: '大石桥石化麟瑞加油站', width: 180, align: 'center' },
14
+];
15
+
16
+// 价格明细表格数据
17
+export const priceDetailData = [
18
+  {
19
+    oilType: '95#',
20
+    weilai0: '7.31',
21
+    dongming0: '7.31',
22
+    zhongshihua0: '7.31',
23
+    dashiqiao0: '7.31',
24
+    weilai1: '7.31',
25
+    dongming1: '7.31',
26
+    zhongshihua1: '7.31',
27
+    dashiqiao1: '7.31',
28
+  },
29
+  {
30
+    oilType: '92#车',
31
+    weilai0: '6.85',
32
+    dongming0: '6.85',
33
+    zhongshihua0: '6.85',
34
+    dashiqiao0: '6.85',
35
+    weilai1: '6.85',
36
+    dongming1: '6.85',
37
+    zhongshihua1: '6.85',
38
+    dashiqiao1: '6.85',
39
+  },
40
+  {
41
+    oilType: '92#车',
42
+    weilai0: '6.85',
43
+    dongming0: '6.85',
44
+    zhongshihua0: '6.85',
45
+    dashiqiao0: '6.85',
46
+    weilai1: '6.85',
47
+    dongming1: '6.85',
48
+    zhongshihua1: '6.85',
49
+    dashiqiao1: '6.85',
50
+  },
51
+  {
52
+    oilType: '92#的士',
53
+    weilai0: '6.85',
54
+    dongming0: '6.85',
55
+    zhongshihua0: '6.85',
56
+    dashiqiao0: '6.85',
57
+    weilai1: '6.85',
58
+    dongming1: '6.85',
59
+    zhongshihua1: '6.85',
60
+    dashiqiao1: '6.85',
61
+  },
62
+  {
63
+    oilType: '92#运卡',
64
+    weilai0: '6.85',
65
+    dongming0: '6.85',
66
+    zhongshihua0: '6.85',
67
+    dashiqiao0: '6.85',
68
+    weilai1: '6.85',
69
+    dongming1: '6.85',
70
+    zhongshihua1: '6.85',
71
+    dashiqiao1: '6.85',
72
+  },
73
+  {
74
+    oilType: '合计',
75
+    weilai0: '',
76
+    dongming0: '',
77
+    zhongshihua0: '',
78
+    dashiqiao0: '',
79
+    weilai1: '',
80
+    dongming1: '',
81
+    zhongshihua1: '',
82
+    dashiqiao1: '',
83
+  },
84
+];
85
+
86
+// 油站策略表格列配置
87
+export const stationStrategyColumns: VxeGridProps['columns'] = [
88
+  { field: 'station', title: '油站', width: 100, align: 'center' },
89
+  { field: 'stationNature', title: '油站性质', width: 120, align: 'center' },
90
+  { field: 'competitiveRelation', title: '竞争关系', width: 120, align: 'center' },
91
+  { field: 'distance', title: '距离(KM)', width: 120, align: 'center' },
92
+  { field: 'discountPolicy', title: '优惠活动', width: 300, align: 'center' },
93
+  { field: 'valueAddedService', title: '增值服务', width: 250, align: 'center' },
94
+  { field: 'equipmentConfiguration', title: '油站设备配置变化', width: 250, align: 'center' },
95
+];
96
+
97
+// 油站策略表格数据
98
+export const stationStrategyData = [
99
+  {
100
+    station: '未来路...',
101
+    stationNature: '-',
102
+    competitiveRelation: '-',
103
+    distance: '-',
104
+    discountPolicy: '92#汽:会员满200优惠0.6元/升 优惠后单价6.46元/升;95#汽:会员满200优惠0.6元/升 优惠后单价6.94元/升 充值500送40元,折合优惠0.9元/升 充值1000送100元,折合优惠1.0元/升 充值2000送260元,折合优惠1.2元/升',
105
+    valueAddedService: '免费洗车、免费加注玻璃水、免费充气、手机充电、免费茶水、免费糖果、赠品、无线网络',
106
+    equipmentConfiguration: '冠德双屏机+ic卡加油机+自助收银机',
107
+  },
108
+  {
109
+    station: '东明石...',
110
+    stationNature: '民营',
111
+    competitiveRelation: '1级(主要)',
112
+    distance: '3.4',
113
+    discountPolicy: '非会员日优惠6毛,周二、周五优惠8毛;6日、16日、26日优惠8毛;平台优惠5毛',
114
+    valueAddedService: '抽纸、自助洗车',
115
+    equipmentConfiguration: '正常油站基本配置',
116
+  },
117
+  {
118
+    station: '中石化...',
119
+    stationNature: '民营',
120
+    competitiveRelation: '1级(主要)',
121
+    distance: '2.8',
122
+    discountPolicy: '非会员优惠6毛,周二、周四优惠8毛;平台优惠8毛',
123
+    valueAddedService: '抽纸、自助洗车、水、饮料、牙膏、洗洁精、抽纸、玻璃水、洗衣液、牙刷、人工清洗',
124
+    equipmentConfiguration: '基本加油设备',
125
+  },
126
+  {
127
+    station: '大石桥...',
128
+    stationNature: '民营',
129
+    competitiveRelation: '1级(主要)',
130
+    distance: '3.4',
131
+    discountPolicy: '油价直降7毛,平台优惠1毛,共计优惠8毛',
132
+    valueAddedService: '抽纸、自助洗车',
133
+    equipmentConfiguration: '油站基本配置',
134
+  },
135
+];

+ 140 - 0
apps/web-ele/src/views/schedule/detail/components/weekly.vue

@@ -0,0 +1,140 @@
1
+<script lang="ts" setup>
2
+import { ref } from 'vue';
3
+import { ElDescriptions, ElDescriptionsItem, ElTag } from 'element-plus';
4
+
5
+// 模拟周报数据
6
+const weeklyData = ref({
7
+  site: '未来路加油站',
8
+  priceAdjustment: '汽油价格调整(三五日提价0.6,其他时间同0.4)',
9
+  activity: '汽车销售部(三五日)员工洗车',
10
+  competitorSituation: '价格优惠0.8',
11
+  competitorChanges: '新增燃油系统',
12
+  completedWork: '站点周边的配套系统升级,反馈应用问题',
13
+  inventorySituation: '站点库存正常/需求调整',
14
+  nextPlan: '员工工作方向为国际站新规培训',
15
+  needCoordination: '系统数据同步功能完善,集成规则后链路数据规则问题',
16
+  safetyMatters: '安全无措施',
17
+  remark: '',
18
+  images: [],
19
+  handleTime: '2025-12-10 07:40:51',
20
+  deadline: '2025-12-14 23:00:00',
21
+  status: '规划完成',
22
+  executor: '要智站务',
23
+  organization: '系统'
24
+});
25
+
26
+// 状态标签配置
27
+const statusConfig: any = {
28
+  '规划完成': { type: 'success', text: '规划完成' },
29
+  '待处理': { type: 'info', text: '待处理' },
30
+  '处理中': { type: 'warning', text: '处理中' },
31
+  '已完成': { type: 'success', text: '已完成' },
32
+  '已关闭': { type: 'danger', text: '已关闭' }
33
+};
34
+</script>
35
+
36
+<template>
37
+  <div class="weekly-container">
38
+    <ElDescriptions class="weekly-info" :column="4">
39
+      <ElDescriptionsItem label="站点:" :span="4">
40
+        {{ weeklyData.site }}
41
+      </ElDescriptionsItem>
42
+      <ElDescriptionsItem label="本周价格调整:" :span="4">
43
+        {{ weeklyData.priceAdjustment }}
44
+      </ElDescriptionsItem>
45
+      <ElDescriptionsItem label="本站活动情况:" :span="4">
46
+        {{ weeklyData.activity }}
47
+      </ElDescriptionsItem>
48
+      <ElDescriptionsItem label="竞争对手情况:" :span="4">
49
+        {{ weeklyData.competitorSituation }}
50
+      </ElDescriptionsItem>
51
+      <ElDescriptionsItem label="竞争对手变化:" :span="4">
52
+        {{ weeklyData.competitorChanges }}
53
+      </ElDescriptionsItem>
54
+      <ElDescriptionsItem label="本周完成工作:" :span="4">
55
+        {{ weeklyData.completedWork }}
56
+      </ElDescriptionsItem>
57
+      <ElDescriptionsItem label="本周库存情况:" :span="4">
58
+        {{ weeklyData.inventorySituation }}
59
+      </ElDescriptionsItem>
60
+      <ElDescriptionsItem label="下周工作计划:" :span="4">
61
+        {{ weeklyData.nextPlan }}
62
+      </ElDescriptionsItem>
63
+      <ElDescriptionsItem label="需领导协调:" :span="4">
64
+        {{ weeklyData.needCoordination }}
65
+      </ElDescriptionsItem>
66
+      <ElDescriptionsItem label="安全、内控、合规、其他事项:" :span="4">
67
+        {{ weeklyData.safetyMatters }}
68
+      </ElDescriptionsItem>
69
+      <ElDescriptionsItem label="备注:" :span="4">
70
+        {{ weeklyData.remark || '-' }}
71
+      </ElDescriptionsItem>
72
+      <ElDescriptionsItem label="图片:" :span="4">
73
+        <div v-if="weeklyData.images && weeklyData.images.length > 0" class="weekly-images">
74
+          <img
75
+            v-for="(image, index) in weeklyData.images"
76
+            :key="index"
77
+            :src="image"
78
+            alt="周报图片"
79
+            class="weekly-image"
80
+          />
81
+        </div>
82
+        <span v-else>-</span>
83
+      </ElDescriptionsItem>
84
+      <ElDescriptionsItem label="处理时间:">
85
+        {{ weeklyData.handleTime }}
86
+      </ElDescriptionsItem>
87
+      <ElDescriptionsItem label="截止时间:">
88
+        {{ weeklyData.deadline }}
89
+      </ElDescriptionsItem>
90
+      <ElDescriptionsItem label="处理状态:">
91
+        <ElTag :type="statusConfig[weeklyData.status]?.type || 'info'">
92
+          {{ statusConfig[weeklyData.status]?.text || weeklyData.status }}
93
+        </ElTag>
94
+      </ElDescriptionsItem>
95
+      <ElDescriptionsItem label="执行人:">
96
+        {{ weeklyData.executor }}
97
+      </ElDescriptionsItem>
98
+      <ElDescriptionsItem label="组织:">
99
+        {{ weeklyData.organization }}
100
+      </ElDescriptionsItem>
101
+    </ElDescriptions>
102
+  </div>
103
+</template>
104
+
105
+<style scoped lang="scss">
106
+.weekly-container {
107
+  width: 100%;
108
+  padding: 16px 0;
109
+}
110
+
111
+.weekly-info {
112
+  :deep(.el-descriptions__label) {
113
+    font-weight: 500;
114
+    color: var(--text-color-secondary);
115
+  }
116
+
117
+  :deep(.el-descriptions__content) {
118
+    color: var(--text-color-primary);
119
+  }
120
+}
121
+
122
+.weekly-images {
123
+  display: flex;
124
+  gap: 12px;
125
+  margin-top: 4px;
126
+
127
+  .weekly-image {
128
+    width: 60px;
129
+    height: 60px;
130
+    cursor: pointer;
131
+    object-fit: cover;
132
+    border-radius: 4px;
133
+    transition: transform 0.2s;
134
+
135
+    &:hover {
136
+      transform: scale(1.05);
137
+    }
138
+  }
139
+}
140
+</style>

+ 146 - 0
apps/web-ele/src/views/schedule/detail/index.vue

@@ -10,10 +10,12 @@ import {
10 10
   ElTag,
11 11
 } from 'element-plus';
12 12
 
13
+import BiddingComponent from './components/bidding.vue';
13 14
 import CheckComponent from './components/check.vue';
14 15
 // 引入检查项组件、评论组件和查阅组件
15 16
 import CommentComponent from './components/comment.vue';
16 17
 import ConsultComponent from './components/consult.vue';
18
+import WeeklyComponent from './components/weekly.vue';
17 19
 
18 20
 // 模拟任务数据
19 21
 const taskData = ref({
@@ -29,8 +31,39 @@ const taskData = ref({
29 31
   taskOwner: '',
30 32
   frequency: '每天一次',
31 33
   creator: '系统',
34
+  images: [
35
+    'https://picsum.photos/200/150?random=1',
36
+    'https://picsum.photos/200/150?random=2',
37
+  ],
38
+  // 处理信息
39
+  handleInfo: {
40
+    handleStatus: '已完成',
41
+    handleSituation: '已完成摄像头抓图AI检查,检查结果正常,无异常情况。',
42
+    handleImages: [
43
+      'https://picsum.photos/200/150?random=3',
44
+      'https://picsum.photos/200/150?random=4',
45
+      'https://picsum.photos/200/150?random=5',
46
+    ],
47
+    handleTime: '2025-12-09 14:30:00',
48
+    handler: '张三',
49
+  },
32 50
 });
33 51
 
52
+// 图片预览相关
53
+const previewVisible = ref(false);
54
+const previewImages = ref<string[]>([]);
55
+
56
+// 预览图片
57
+const previewImage = (imageUrl: string) => {
58
+  previewImages.value = [imageUrl];
59
+  previewVisible.value = true;
60
+};
61
+
62
+// 关闭图片预览
63
+const closePreview = () => {
64
+  previewVisible.value = false;
65
+};
66
+
34 67
 // 状态标签配置
35 68
 const statusConfig: any = {
36 69
   待处理: { type: 'info', text: '待处理' },
@@ -105,6 +138,22 @@ const handleTransferTask = () => {
105 138
         <ElDescriptionsItem label="标准指引:" :span="4">
106 139
           {{ taskData.standardGuide || '-' }}
107 140
         </ElDescriptionsItem>
141
+        <ElDescriptionsItem label="任务图片:" :span="4">
142
+          <div
143
+            v-if="taskData.images && taskData.images.length > 0"
144
+            class="task-images"
145
+          >
146
+            <img
147
+              v-for="(image, index) in taskData.images"
148
+              :key="index"
149
+              :src="image"
150
+              alt="任务图片"
151
+              class="task-image"
152
+              @click="previewImage(image)"
153
+            />
154
+          </div>
155
+          <span v-else>-</span>
156
+        </ElDescriptionsItem>
108 157
         <ElDescriptionsItem label="执行人:">
109 158
           {{ taskData.executor }}
110 159
         </ElDescriptionsItem>
@@ -134,6 +183,77 @@ const handleTransferTask = () => {
134 183
       </ElDescriptions>
135 184
     </ElCard>
136 185
 
186
+    <!--竞价-->
187
+    <ElCard>
188
+      <template #header>
189
+        <div class="flex items-center justify-between">
190
+          <span class="text-lg font-bold text-gray-800">竞价信息</span>
191
+        </div>
192
+      </template>
193
+      <BiddingComponent />
194
+    </ElCard>
195
+
196
+    <!-- 周报信息 -->
197
+    <ElCard class="mt-4">
198
+      <template #header>
199
+        <div class="flex items-center justify-between">
200
+          <span class="text-lg font-bold text-gray-800">周报信息</span>
201
+        </div>
202
+      </template>
203
+      <WeeklyComponent />
204
+    </ElCard>
205
+
206
+    <!-- 处理信息组件 -->
207
+    <ElCard class="mt-4">
208
+      <template #header>
209
+        <div class="flex items-center justify-between">
210
+          <span class="text-lg font-bold text-gray-800">处理信息</span>
211
+        </div>
212
+      </template>
213
+      <ElDescriptions class="task-info" :column="4">
214
+        <ElDescriptionsItem label="处理状态:" :span="4">
215
+          <ElTag
216
+            :type="
217
+              statusConfig[taskData.handleInfo.handleStatus]?.type || 'info'
218
+            "
219
+          >
220
+            {{
221
+              statusConfig[taskData.handleInfo.handleStatus]?.text ||
222
+              taskData.handleInfo.handleStatus
223
+            }}
224
+          </ElTag>
225
+        </ElDescriptionsItem>
226
+        <ElDescriptionsItem label="处理情况:" :span="4">
227
+          {{ taskData.handleInfo.handleSituation || '-' }}
228
+        </ElDescriptionsItem>
229
+        <ElDescriptionsItem label="处理图片:" :span="4">
230
+          <div
231
+            v-if="
232
+              taskData.handleInfo.handleImages &&
233
+              taskData.handleInfo.handleImages.length > 0
234
+            "
235
+            class="task-images"
236
+          >
237
+            <img
238
+              v-for="(image, index) in taskData.handleInfo.handleImages"
239
+              :key="index"
240
+              :src="image"
241
+              alt="处理图片"
242
+              class="task-image"
243
+              @click="previewImage(image)"
244
+            />
245
+          </div>
246
+          <span v-else>-</span>
247
+        </ElDescriptionsItem>
248
+        <ElDescriptionsItem label="处理人:">
249
+          {{ taskData.handleInfo.handler || '-' }}
250
+        </ElDescriptionsItem>
251
+        <ElDescriptionsItem label="处理时间:">
252
+          {{ taskData.handleInfo.handleTime || '-' }}
253
+        </ElDescriptionsItem>
254
+      </ElDescriptions>
255
+    </ElCard>
256
+
137 257
     <!-- 检查项组件 -->
138 258
     <ElCard class="mt-4">
139 259
       <template #header>
@@ -164,6 +284,13 @@ const handleTransferTask = () => {
164 284
       <CommentComponent />
165 285
     </ElCard>
166 286
   </Page>
287
+
288
+  <!-- 图片预览组件 -->
289
+  <ElImageViewer
290
+    v-if="previewVisible"
291
+    :url-list="previewImages"
292
+    @close="closePreview"
293
+  />
167 294
 </template>
168 295
 
169 296
 <style scoped lang="scss">
@@ -198,4 +325,23 @@ const handleTransferTask = () => {
198 325
   //   padding: 8px 0;
199 326
   // }
200 327
 }
328
+
329
+.task-images {
330
+  display: flex;
331
+  gap: 12px;
332
+  margin-top: 4px;
333
+
334
+  .task-image {
335
+    width: 60px;
336
+    height: 60px;
337
+    cursor: pointer;
338
+    object-fit: cover;
339
+    border-radius: 4px;
340
+    transition: transform 0.2s;
341
+
342
+    &:hover {
343
+      transform: scale(1.05);
344
+    }
345
+  }
346
+}
201 347
 </style>