| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- <template>
- <view class="task-management">
- <view class="fixed-area">
- <view class="title">
- <text class="title-text">龙飞街加油站</text>
- </view>
- <view>
- <wd-tabs v-model="tab">
- <block v-for="item in tabs" :key="item">
- <wd-tab :title="`${item}`" :name="item" />
- </block>
- </wd-tabs>
- </view>
- </view>
- <scroll-view class="task-container" scroll-y>
- <view class="tasks">
- <view
- v-for="(task, index) in currentTasks"
- :key="index"
- class="task-item"
- >
- <!-- 任务描述 -->
- <view class="task-description">
- <text class="task-number">{{ index + 1 }}.</text>
- <text class="task-text"
- >{{ task.description }}
- <wd-icon
- v-if="task?.icon"
- :name="task?.icon"
- size="32rpx"
- @click="() => (popupshow.centershow = true)"
- ></wd-icon>
- </text>
- </view>
- <!-- 操作说明 -->
- <view v-if="task.instructions" class="task-instructions">
- <text class="instructions-text">{{ task.instructions }}</text>
- </view>
- <!-- 示例图片 -->
- <view v-if="task.examples.length > 0" class="example-images">
- <view
- v-for="(example, idx) in task.examples"
- :key="idx"
- class="example-image"
- >
- <image :src="example" mode="aspectFill"></image>
- <text class="example-text">示例</text>
- </view>
- </view>
- <!-- 已上传图片 -->
- <view v-if="task.images.length > 0" class="uploaded-images">
- <view
- v-for="(image, idx) in task.images"
- :key="idx"
- class="uploaded-image"
- >
- <image :src="image" mode="aspectFill"></image>
- </view>
- </view>
- <!-- 上传按钮 -->
- <view
- v-if="task.isimages"
- class="upload-btn"
- @tap="chooseImage(index)"
- >
- <view class="btn-content">
- <text class="btn-icon">+</text>
- <text class="btn-text">拍照</text>
- </view>
- </view>
- <!-- 状态选择 -->
- <view v-if="!task.details" class="status-select">
- <view class="radio-group">
- <view class="radio-item" @tap="toggleTaskStatus(index)">
- <view
- class="radio"
- :class="{ selected: task.status === 'normal' }"
- ></view>
- <text class="radio-text">正常</text>
- </view>
- <view class="radio-item" @tap="toggleTaskStatus(index)">
- <view
- class="radio"
- :class="{ selected: task.status === 'abnormal' }"
- ></view>
- <text class="radio-text">异常</text>
- </view>
- </view>
- </view>
- <!-- 带详情的状态选择 -->
- <view v-if="task.details" class="detail-status">
- <text class="detail-name">{{ task.details[0].name }}</text>
- <view class="radio-group">
- <view class="radio-item" @tap="toggleTaskStatus(index, 0)">
- <view
- class="radio"
- :class="{ selected: task.details[0].status === 'normal' }"
- ></view>
- <text class="radio-text">正常</text>
- </view>
- <view class="radio-item" @tap="toggleTaskStatus(index, 0)">
- <view
- class="radio"
- :class="{ selected: task.details[0].status === 'abnormal' }"
- ></view>
- <text class="radio-text">异常</text>
- </view>
- </view>
- <view class="detail-items">
- <view
- v-for="(detail, idx) in task.details.slice(1)"
- :key="idx"
- class="detail-item"
- >
- <view class="detail-name">{{ detail.name }}</view>
- <view
- class="radio-item"
- @tap="toggleTaskStatus(index, idx + 1)"
- >
- <view
- class="radio"
- :class="{ selected: detail.status === 'normal' }"
- ></view>
- <text class="radio-text">正常</text>
- </view>
- <view
- class="radio-item"
- @tap="toggleTaskStatus(index, idx + 1)"
- >
- <view
- class="radio"
- :class="{ selected: detail.status === 'abnormal' }"
- ></view>
- <text class="radio-text">异常</text>
- </view>
- </view>
- </view>
- </view>
- </view>
- </view>
- </scroll-view>
- <centerpopup v-model:centershow="popupshow.centershow" />
- <bottompopup v-model:bottomshow="popupshow.bottomshow" />
- <!-- 确定按钮 -->
- <view class="confirm-btn">
- <button class="btn" @click="submitTasks">确 定</button>
- </view>
- </view>
- </template>
- <script lang="ts" setup>
- import { ref, computed } from 'vue'
- import useUpload from '@/hooks/useUpload'
- import centerpopup from '../popup/centerpopup.vue'
- import bottompopup from '../popup/bottompopup.vue'
- const popupshow = ref({
- centershow: false,
- bottomshow: false,
- })
- // const popupshow = ref({})
- const tab = ref('前庭')
- const tabs = ['营销', '出入口', '前庭', '便利店', '洗手间']
- // 定义任务类型
- interface Task {
- id: string
- type: string
- description: string
- icon?: string
- instructions: string
- examples: string[]
- images: string[]
- status: 'normal' | 'abnormal'
- isimages: boolean
- details?: {
- name: string
- status: 'normal' | 'abnormal'
- }[]
- }
- // 任务数据
- const tasks = ref<Task[]>([
- {
- id: '1',
- type: '前庭',
- description:
- '[AI] [卫生] 前庭海报整齐不歪斜,干净无灰尘污渍(立柱、灯箱、展架等)。',
- instructions: '拍照:按照示例图拍摄前庭内海报宣传物,可上传多张照片',
- examples: [
- 'https://picsum.photos/id/1018/200/150',
- 'https://picsum.photos/id/1019/200/150',
- ],
- images: [],
- isimages: true,
- status: 'normal',
- },
- {
- id: '2',
- type: '前庭',
- description: '[卫生] 抽油枪栓是否出现空转或存在明显渗油。',
- icon: 'help-circle',
- instructions: '',
- examples: [],
- images: [],
- isimages: false,
- status: 'normal',
- details: [{ name: '12号枪', status: 'normal' }],
- },
- {
- id: '3',
- type: '前庭',
- description:
- '[AI] [卫生] 前庭海报整齐不歪斜,干净无灰尘污渍(立柱、灯箱、展架等)。',
- instructions: '拍照:按照示例图拍摄前庭内海报宣传物,可上传多张照片',
- examples: [
- 'https://picsum.photos/id/1018/200/150',
- 'https://picsum.photos/id/1019/200/150',
- ],
- images: ['https://picsum.photos/id/1025/200/150'],
- isimages: true,
- status: 'normal',
- },
- ])
- // 根据当前标签筛选任务
- const currentTasks = computed(() => {
- return tasks.value.filter((task) => task.type === tab.value)
- })
- // 选择图片
- const chooseImage = (index: number) => {
- // 为每个上传请求创建独立的upload实例,确保能正确处理对应的任务索引
- const { run: uploadImage } = useUpload({
- fileType: 'image',
- success: (res) => {
- console.log('上传成功', res)
- // 将上传成功的图片URL添加到对应任务的images数组中
- // 假设res包含图片URL,实际结构需要根据后端返回调整
- const imageUrl = typeof res === 'string' ? res : res.url || ''
- if (imageUrl) {
- tasks.value[index].images.push(imageUrl)
- }
- },
- error: (err) => {
- console.error('上传失败', err)
- },
- })
- uploadImage()
- }
- // 切换任务状态
- const toggleTaskStatus = (taskIndex: number, detailIndex?: number) => {
- const task = tasks.value[taskIndex]
- if (detailIndex !== undefined && task.details) {
- // 有子项的任务
- const detail = task.details[detailIndex]
- detail.status = detail.status === 'normal' ? 'abnormal' : 'normal'
- // 检查是否有任一子项异常
- task.status = task.details.some((d) => d.status === 'abnormal')
- ? 'abnormal'
- : 'normal'
- } else {
- // 无子项的任务
- task.status = task.status === 'normal' ? 'abnormal' : 'normal'
- }
- if (task.status === 'abnormal') {
- popupshow.value.bottomshow = true
- }
- }
- // 提交任务
- const submitTasks = () => {
- console.log('提交任务', tasks.value)
- // 这里可以添加提交逻辑
- uni.showToast({
- title: '提交成功',
- icon: 'success',
- })
- }
- // 关闭弹窗按钮
- // const handleClose = () => {
- // popupshow.value = false
- // }
- </script>
- <style lang="scss" scoped>
- .task-management {
- display: flex;
- flex-direction: column;
- height: 1500rpx;
- overflow: hidden;
- .fixed-area {
- flex-shrink: 0; // 不让它被压缩
- background-color: #fff;
- position: sticky; // 若想随外层滚就 sticky;想完全固定用 fixed 即可
- top: 0;
- z-index: 10;
- }
- .title {
- width: 100%;
- height: 128rpx;
- background-color: #4a80c3;
- display: flex;
- align-items: center;
- box-sizing: border-box;
- padding-left: 46rpx;
- }
- .title-text {
- font-size: 36rpx;
- font-weight: 500;
- color: #fff;
- }
- // // 任务容器
- // .task-container {
- // flex: 1;
- // padding: 0 30rpx;
- // .tasks {
- // padding: 20rpx 0;
- // }
- // }
- .task-container {
- flex: 1; // 占剩余高度
- overflow-y: auto; // 仅这里滚动
- padding: 0 30rpx;
- }
- // 任务项
- .task-item {
- margin-bottom: 40rpx;
- // 任务描述
- .task-description {
- display: flex;
- margin-bottom: 16rpx;
- .task-number {
- font-size: 28rpx;
- color: #333;
- margin-right: 8rpx;
- font-weight: 500;
- }
- .task-text {
- font-size: 28rpx;
- font-weight: 400;
- color: #333;
- line-height: 44rpx;
- }
- }
- // 操作说明
- .task-instructions {
- margin-bottom: 20rpx;
- .instructions-text {
- font-size: 24rpx;
- color: #666;
- line-height: 36rpx;
- }
- }
- // 示例图片
- .example-images {
- display: flex;
- gap: 16rpx;
- margin-bottom: 20rpx;
- .example-image {
- width: 140rpx;
- height: 100rpx;
- position: relative;
- image {
- width: 100%;
- height: 100%;
- border-radius: 8rpx;
- }
- .example-text {
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- background-color: rgba(0, 0, 0, 0.5);
- color: white;
- font-size: 20rpx;
- text-align: center;
- padding: 4rpx 0;
- border-radius: 0 0 8rpx 8rpx;
- }
- }
- }
- // 已上传图片
- .uploaded-images {
- display: flex;
- gap: 16rpx;
- margin-bottom: 20rpx;
- .uploaded-image {
- width: 140rpx;
- height: 100rpx;
- image {
- width: 100%;
- height: 100%;
- border-radius: 8rpx;
- }
- }
- }
- // 上传按钮
- .upload-btn {
- width: 140rpx;
- height: 100rpx;
- border: 2rpx dashed #ccc;
- border-radius: 8rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-bottom: 24rpx;
- .btn-content {
- display: flex;
- flex-direction: column;
- align-items: center;
- .btn-icon {
- font-size: 40rpx;
- color: #999;
- line-height: 40rpx;
- }
- .btn-text {
- font-size: 24rpx;
- color: #999;
- margin-top: 4rpx;
- }
- }
- }
- // 状态选择
- .status-select {
- margin-bottom: 20rpx;
- .radio-group {
- display: flex;
- gap: 40rpx;
- }
- }
- // 带详情的状态选择
- .detail-status {
- margin-bottom: 20rpx;
- .detail-name {
- font-size: 28rpx;
- color: #333;
- margin-right: 20rpx;
- // margin-bottom: 10rpx;
- }
- .radio-group {
- display: flex;
- gap: 40rpx;
- }
- .detail-items {
- margin-top: 16rpx;
- display: flex;
- flex-wrap: wrap;
- gap: 40rpx;
- }
- }
- // 单选按钮
- .radio-group {
- .radio-item {
- // margin-top: 50rpx;
- display: flex;
- align-items: center;
- gap: 8rpx;
- .radio {
- width: 32rpx;
- height: 32rpx;
- border: 2rpx solid #ccc;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- &.selected {
- border-color: #215acd;
- // background-color: #4a80c3;
- &::after {
- content: '';
- width: 16rpx;
- height: 16rpx;
- border-radius: 50%;
- background-color: #215acd;
- }
- }
- }
- .radio-text {
- font-size: 28rpx;
- color: #333;
- }
- }
- }
- }
- // 确定按钮
- .confirm-btn {
- padding: 20rpx 30rpx;
- background-color: white;
- border-top: 1rpx solid #eee;
- .btn {
- width: 100%;
- height: 80rpx;
- background-color: #215acd;
- color: white;
- font-size: 32rpx;
- border-radius: 12rpx;
- font-weight: 400;
- border: none;
- outline: none;
- }
- }
- }
- </style>
|