| @ -1,2 +1,599 @@ | |||
| <template> | |||
| </template> | |||
| <view class="container"> | |||
| <view class="header"> | |||
| <view class="header-bg"> | |||
| <image | |||
| src="/static/会员背景.png" | |||
| class="header-img" | |||
| mode="scaleToFill" | |||
| /> | |||
| <text class="header-title">会员中心</text> | |||
| </view> | |||
| <view class="header-content"> | |||
| <view class="zuanshi"> | |||
| <image | |||
| src="/static/会员钻石.png" | |||
| mode="scaleToFill" | |||
| class="zuanshi-img" | |||
| /> | |||
| </view> | |||
| <image | |||
| src="/static/VIP.png" | |||
| mode="aspectFit" | |||
| class="VIP-img" | |||
| /> | |||
| <text class="intro">共19项会员特权 | 3 项年VIP专属特权</text> | |||
| <view class="border" /> | |||
| <view class="info"> | |||
| <view class="avatar-box"> | |||
| <image | |||
| :src="userInfo.avatar" | |||
| mode="aspectFill" | |||
| class="avatar" | |||
| /> | |||
| <text class="name">{{userInfo.name}}</text> | |||
| </view> | |||
| <uv-button text="立即开通" | |||
| type="primary" | |||
| :customStyle="{ | |||
| width: '160rpx', | |||
| height: '60rpx', | |||
| borderRadius: '198rpx', | |||
| backgroundColor: '#06DADC', | |||
| color: '#fff', | |||
| fontSize: '28rpx', | |||
| fontWeight: '500', | |||
| lineHeight: '60rpx', | |||
| letterSpacing: '0%', | |||
| verticalAlign: 'middle', | |||
| }" /> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 会员权益 --> | |||
| <view class="benefits-section"> | |||
| <view class="benefits-title">会员权益</view> | |||
| <view class="benefits-list"> | |||
| <!-- 碎片学习 系统掌握 --> | |||
| <view class="benefit-item"> | |||
| <view class="benefit-content"> | |||
| <view class="benefit-title">碎片学习 系统掌握</view> | |||
| <view class="benefit-desc">根据薄弱点智能推荐,每节课3-5分钟,碎片化完成系统学习</view> | |||
| </view> | |||
| <view class="benefit-icon"> | |||
| <image src="/static/会员图片1.png" mode="aspectFit"></image> | |||
| </view> | |||
| </view> | |||
| <!-- 匹配水平 --> | |||
| <view class="benefit-item"> | |||
| <view class="benefit-content"> | |||
| <view class="benefit-title">匹配水平</view> | |||
| <view class="benefit-desc">依据水平精准推课,不做无用功快速提升</view> | |||
| </view> | |||
| <view class="benefit-icon"> | |||
| <image src="/static/会员图片2.png" mode="aspectFit"></image> | |||
| </view> | |||
| </view> | |||
| <!-- 科学闭环测 讲练结合 --> | |||
| <view class="benefit-item"> | |||
| <view class="benefit-content"> | |||
| <view class="benefit-title">科学闭环测 讲练结合</view> | |||
| <view class="benefit-desc">精心设计科学的学习流程 「测试-讲解-练习-检验」知识掌握更牢固</view> | |||
| </view> | |||
| <view class="benefit-icon"> | |||
| <image src="/static/会员图片3.png" mode="aspectFit"></image> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 以下内容为成为会员才能看到的 --> | |||
| <!-- 学习计划 --> | |||
| <view class="study-plan-section"> | |||
| <view class="section-title">学习计划</view> | |||
| <view class="plan-books"> | |||
| <view | |||
| v-for="(book, index) in studyPlanBooks" | |||
| :key="index" | |||
| class="plan-book-item" | |||
| :class="{ 'active-book': index === 1 }" | |||
| > | |||
| <view class="plan-book-cover"> | |||
| <image :src="book.cover" mode="aspectFill"></image> | |||
| <!-- 学习中标识 --> | |||
| <view v-if="index === 1" class="studying-badge"> | |||
| <view class="studying-icon"/> | |||
| <text>学习中</text> | |||
| </view> | |||
| </view> | |||
| <view class="plan-book-info"> | |||
| <text class="plan-book-title" :class="{ 'highlight-title': index === 1 }">{{ book.title }}</text> | |||
| <view class="plan-book-meta" > | |||
| <text class="plan-book-grade" :class="{ 'highlight-title': index === 1 }">{{ book.grade }}/</text> | |||
| <image v-if="index !== 1" src="/static/播放图标.png" class="plan-book-duration-icon" /> | |||
| <image v-else src="/static/播放图标高亮.png" class="plan-book-duration-icon" /> | |||
| <text class="plan-book-duration" :class="{ 'highlight-title': index === 1 }">{{ book.duration }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 学习推荐 --> | |||
| <view class="study-recommend-section"> | |||
| <view class="section-header"> | |||
| <text class="section-title">学习推荐</text> | |||
| <view class="section-more"> | |||
| <text>更多</text> | |||
| <uv-icon name="arrow-right" size="14" color="#8B8B8B"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="recommend-grid"> | |||
| <view | |||
| v-for="(book, index) in recommendBooks" | |||
| :key="index" | |||
| class="recommend-grid-item" | |||
| > | |||
| <view class="recommend-grid-cover"> | |||
| <image :src="book.cover" mode="aspectFill"></image> | |||
| </view> | |||
| <view class="recommend-grid-info"> | |||
| <text class="recommend-grid-title">{{ book.title }}</text> | |||
| <view class="recommend-grid-meta"> | |||
| <text class="recommend-grid-grade">{{ book.grade }}/</text> | |||
| <image src="/static/播放图标.png" class="recommend-grid-duration-icon" /> | |||
| <text class="recommend-grid-duration">{{ book.duration }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default{ | |||
| data() { | |||
| return { | |||
| userInfo: { | |||
| name: '战斗世界', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| // 学习计划书籍数据 | |||
| studyPlanBooks: [ | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '精讲短文', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '精讲短文', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '精讲短文', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| } | |||
| ], | |||
| // 学习推荐书籍数据 | |||
| recommendBooks: [ | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '小王子', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '自私的巨人', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '百万英镑', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: 'MATILDA', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: 'Pride and Prejudice', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| }, | |||
| { | |||
| cover: '/static/默认图片.png', | |||
| title: '温德尔·范·德拉南', | |||
| grade: '四级', | |||
| duration: '03:24' | |||
| } | |||
| ] | |||
| } | |||
| }, | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .container { | |||
| min-height: 100%; | |||
| } | |||
| .header{ | |||
| width: 100%; | |||
| .header-bg{ | |||
| position: relative; | |||
| width: 100%; | |||
| height: 400rpx; | |||
| // background: red; | |||
| .header-img{ | |||
| width: 100%; | |||
| height: 400rpx; | |||
| } | |||
| .header-title{ | |||
| font-size: 32rpx; | |||
| color: black; | |||
| position: absolute; | |||
| top: 100rpx; | |||
| font-weight: 500; | |||
| left: 50%; | |||
| transform: translateX(-50%); | |||
| } | |||
| } | |||
| .header-content{ | |||
| margin: 0 18rpx; | |||
| margin-top: -150rpx; | |||
| height: 256rpx; | |||
| border-radius: 32rpx; | |||
| border-width: 2rpx; | |||
| padding: 40rpx; | |||
| background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #F0FBFF 100%); | |||
| border: 2rpx solid #06DADC12; | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 28rpx; | |||
| position: relative; | |||
| .zuanshi{ | |||
| position: absolute; | |||
| width: 190rpx; | |||
| height: 190rpx; | |||
| top: -80rpx; | |||
| right: 0; | |||
| .zuanshi-img{ | |||
| width: 190rpx; | |||
| height: 190rpx; | |||
| } | |||
| } | |||
| .VIP-img{ | |||
| width: 80rpx; | |||
| height: 50rpx; | |||
| } | |||
| .border{ | |||
| width: 100%; | |||
| // height: 2rpx; | |||
| border: 2rpx solid; | |||
| border-image-source: linear-gradient(90deg, rgba(228, 255, 255, 0) 0%, #C3EFEF 50.48%, rgba(228, 255, 255, 0) 100%); | |||
| border-image-slice: 1; | |||
| } | |||
| .intro{ | |||
| font-size: 28rpx; | |||
| line-height: 36rpx; | |||
| letter-spacing: 0%; | |||
| vertical-align: middle; | |||
| color: #09B1B3; | |||
| } | |||
| .info{ | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| .avatar-box{ | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| .name{ | |||
| font-weight: 600; | |||
| font-size: 36rpx; | |||
| line-height: 44rpx; | |||
| letter-spacing: 0%; | |||
| vertical-align: middle; | |||
| color: #252545; | |||
| } | |||
| .avatar{ | |||
| width: 60rpx; | |||
| height: 60rpx; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* 会员权益样式 */ | |||
| .benefits-section { | |||
| margin-top: 40rpx; | |||
| padding: 0 30rpx; | |||
| } | |||
| .benefits-title { | |||
| font-size: 36rpx; | |||
| font-weight: bold; | |||
| color: #191919; | |||
| margin-bottom: 32rpx; | |||
| } | |||
| .benefits-list { | |||
| display: flex; | |||
| flex-direction: column; | |||
| gap: 32rpx; | |||
| } | |||
| .benefit-item { | |||
| background: #F8F8F8; | |||
| border: 1px solid #FFFFFF; | |||
| border-radius: 48rpx; | |||
| padding: 27rpx 40rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| } | |||
| .benefit-content { | |||
| flex: 1; | |||
| margin-right: 40rpx; | |||
| } | |||
| .benefit-title { | |||
| font-size: 32rpx; | |||
| font-weight: 600; | |||
| color: #333; | |||
| margin-bottom: 16rpx; | |||
| } | |||
| .benefit-desc { | |||
| font-size: 24rpx; | |||
| color: #09B1B3; | |||
| line-height: 36rpx; | |||
| } | |||
| .benefit-icon { | |||
| width: 152rpx; | |||
| height: 152rpx; | |||
| // flex-shrink: 0; | |||
| } | |||
| .benefit-icon image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| /* 学习计划样式 */ | |||
| .study-plan-section { | |||
| margin-top: 40rpx; | |||
| padding: 0 30rpx; | |||
| } | |||
| .section-title { | |||
| font-size: 36rpx; | |||
| font-weight: 500; | |||
| color: #191919; | |||
| margin-bottom: 32rpx; | |||
| } | |||
| .plan-books { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: flex-end; | |||
| gap: 78rpx; | |||
| padding: 20rpx 0; | |||
| } | |||
| .plan-book-item { | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: center; | |||
| transition: all 0.3s ease; | |||
| &.active-book { | |||
| transform: scale(1.15); | |||
| .plan-book-cover { | |||
| // box-shadow: 0 8rpx 24rpx rgba(6, 218, 220, 0.3); | |||
| } | |||
| } | |||
| } | |||
| .plan-book-cover { | |||
| width: 172rpx; | |||
| height: 230rpx; | |||
| border-radius: 16rpx; | |||
| overflow: hidden; | |||
| margin-bottom: 16rpx; | |||
| position: relative; | |||
| box-shadow: 0px 4px 4px 0px #C0BCBA75; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| .studying-badge { | |||
| position: absolute; | |||
| bottom: 0rpx; | |||
| right: 0rpx; | |||
| background: #00000099; | |||
| color: #fff; | |||
| padding: 6rpx 10rpx; | |||
| border-radius: 20rpx; | |||
| font-size: 18rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| gap: 6rpx; | |||
| .studying-icon{ | |||
| width: 10rpx; | |||
| height: 10rpx; | |||
| background: $primary-color; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| } | |||
| .plan-book-info { | |||
| text-align: center; | |||
| .plan-book-title { | |||
| font-size: 28rpx; | |||
| font-weight: 700; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| display: block; | |||
| &.highlight-title { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| .plan-book-meta { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| gap: 8rpx; | |||
| .plan-book-duration-icon { | |||
| width: 20rpx; | |||
| height: 20rpx; | |||
| } | |||
| .plan-book-grade { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| &.highlight-title { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| .plan-book-duration { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| &.highlight-title { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* 学习推荐样式 */ | |||
| .study-recommend-section { | |||
| margin-top: 40rpx; | |||
| padding: 0 30rpx; | |||
| } | |||
| .section-header { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| margin-bottom: 24rpx; | |||
| .section-more { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 4rpx; | |||
| text { | |||
| font-size: 24rpx; | |||
| color: #8B8B8B; | |||
| } | |||
| } | |||
| } | |||
| .recommend-grid { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 32rpx; | |||
| .recommend-grid-item { | |||
| width: 208rpx; | |||
| display: flex; | |||
| flex-direction: column; | |||
| .recommend-grid-cover { | |||
| box-shadow: 0px 4px 4px 0px #C0BCBA75; | |||
| width: 100%; | |||
| height: 278rpx; | |||
| border-radius: 16rpx; | |||
| overflow: hidden; | |||
| margin-bottom: 16rpx; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| } | |||
| } | |||
| .recommend-grid-info { | |||
| padding: 6rpx; | |||
| .recommend-grid-title { | |||
| font-size: 28rpx; | |||
| font-weight: 700; | |||
| color: #333; | |||
| margin-bottom: 14rpx; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| } | |||
| .recommend-grid-meta { | |||
| display: flex; | |||
| align-items: center; | |||
| .recommend-grid-duration-icon { | |||
| width: 24rpx; | |||
| height: 24rpx; | |||
| margin-right: 12rpx; | |||
| } | |||
| .recommend-grid-grade { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| margin-right: 8rpx; | |||
| } | |||
| .recommend-grid-duration { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -1,608 +0,0 @@ | |||
| <template> | |||
| <view class="container"> | |||
| <view class="header"> | |||
| <!-- 大Tab:维修记录/保养记录 --> | |||
| <view class="main-tabs"> | |||
| <view | |||
| class="tab-item" | |||
| :class="{ active: activeMainTab === 'repair' }" | |||
| @click="switchMainTab('repair')" | |||
| > | |||
| <text class="tab-text">维修记录</text> | |||
| <view class="tab-underline" v-if="activeMainTab === 'repair'"></view> | |||
| </view> | |||
| <view | |||
| class="tab-item" | |||
| :class="{ active: activeMainTab === 'maintain' }" | |||
| @click="switchMainTab('maintain')" | |||
| > | |||
| <text class="tab-text">保养记录</text> | |||
| <view class="tab-underline" v-if="activeMainTab === 'maintain'"></view> | |||
| </view> | |||
| </view> | |||
| <!-- 筛选按钮区域 --> | |||
| <view class="picker-buttons"> | |||
| <view class="picker-btn" :class="{ active: selectedTime }" @click="showTimePicker" > | |||
| <text class="btn-text">{{ selectedTime || '时间' }}</text> | |||
| <text class="arrow-icon">▼</text> | |||
| </view> | |||
| <view class="picker-btn" :class="{ active: selectedPerson }" @click="showPersonPicker" > | |||
| <text class="btn-text">{{ selectedPerson.label || '人员' }}</text> | |||
| <text class="arrow-icon">▼</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 日期选择器 --> | |||
| <uv-datetime-picker | |||
| confirm-color="#C70019" | |||
| ref="timePicker" | |||
| mode="date" | |||
| @confirm="onTimeConfirm" | |||
| ></uv-datetime-picker> | |||
| <!-- 人员选择器 --> | |||
| <uv-picker | |||
| ref="personPicker" | |||
| :columns="personColumns" | |||
| @confirm="onPersonConfirm" | |||
| @cancel="onPersonCancel" | |||
| keyName="label" | |||
| title="选择人员" | |||
| confirmColor="#C70019" | |||
| ></uv-picker> | |||
| <!-- 内容区域 --> | |||
| <view class="content-area"> | |||
| <!-- 记录item --> | |||
| <!-- 加载动画容器 --> | |||
| <view v-if="list.length"> | |||
| <view class="record-item" v-for="(record, index) in list" :key="index"> | |||
| <!-- 维修记录 --> | |||
| <template v-if="activeMainTab === 'repair'"> | |||
| <!-- 基本信息 --> | |||
| <view class="info-row"> | |||
| <text class="label">维修人</text> | |||
| <text class="value">{{ record.repairName }}</text> | |||
| </view> | |||
| <view class="info-row"> | |||
| <text class="label">联系方式</text> | |||
| <text class="value">{{ record.phone }}</text> | |||
| </view> | |||
| <view class="info-row"> | |||
| <text class="label">维修日期</text> | |||
| <text class="value">{{ record.repairDate }}</text> | |||
| </view> | |||
| <view class="info-row"> | |||
| <text class="label">处理内容</text> | |||
| </view> | |||
| <!-- 处理内容文本区域 --> | |||
| <view class="content-text"> | |||
| <text>{{ record.content }}</text> | |||
| </view> | |||
| <!-- 上传图片 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">上传图片</text> | |||
| </view> | |||
| <view class="image-container" v-if="!collapsedStates[index]"> | |||
| <image class="uploaded-image" v-for="(value, index) in record.image.split(',')" :key="index" :src="value" mode="aspectFill"></image> | |||
| </view> | |||
| <!-- 是否产生费用 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">是否产生费用</text> | |||
| <text class="value red-text">{{ record.isExpend === '1' || record.isExpend === 1 ? '是' : '否' }}</text> | |||
| </view> | |||
| </template> | |||
| <!-- 保养记录 --> | |||
| <template v-else> | |||
| <!-- 基本信息 --> | |||
| <view class="info-row"> | |||
| <text class="label">保养人</text> | |||
| <text class="value">{{ record.maintenanceName }}</text> | |||
| </view> | |||
| <view class="info-row"> | |||
| <text class="label">保养日期</text> | |||
| <text class="value">{{ record.maintenanceDate }}</text> | |||
| </view> | |||
| <view class="info-row"> | |||
| <text class="label">保养前状态</text> | |||
| </view> | |||
| <!-- 保养前状态文本区域 --> | |||
| <view class="content-text"> | |||
| <text>{{ record.stateFrontText }}</text> | |||
| </view> | |||
| <!-- 保养前图片 --> | |||
| <view class="image-container" v-if="!collapsedStates[index]"> | |||
| <image | |||
| class="uploaded-image" | |||
| v-for="(img, imgIndex) in record.stateFrontImage.split(',')" | |||
| :key="imgIndex" | |||
| :src="img" | |||
| mode="aspectFill" | |||
| ></image> | |||
| </view> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">保养后状态</text> | |||
| </view> | |||
| <!-- 保养后状态文本区域 --> | |||
| <view class="content-text" v-if="!collapsedStates[index]"> | |||
| <text>{{ record.stateBackText }}</text> | |||
| </view> | |||
| <!-- 保养后图片 --> | |||
| <view class="image-container" v-if="!collapsedStates[index]"> | |||
| <image | |||
| class="uploaded-image" | |||
| v-for="(img, imgIndex) in record.stateBackImage.split(',')" | |||
| :key="'after-' + imgIndex" | |||
| :src="img" | |||
| mode="aspectFill" | |||
| ></image> | |||
| </view> | |||
| <!-- 是否产生费用 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">是否产生费用</text> | |||
| <text class="value red-text">{{ record.isExpend === '1'||record.isExpend === 1 ? '是' : '否' }}</text> | |||
| </view> | |||
| </template> | |||
| <!-- 产生费用 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">产生费用</text> | |||
| <text class="value red-text">{{ record.amount }}</text> | |||
| </view> | |||
| <!-- 费用详情表格 --> | |||
| <view class="cost-table" v-if="!collapsedStates[index]"> | |||
| <view class="table-header"> | |||
| <text class="header-cell">费用名称</text> | |||
| <text class="header-cell">数量</text> | |||
| <text class="header-cell">金额</text> | |||
| </view> | |||
| <view class="table-row" v-for="(item, costIndex) in record.exhibitMaintenanceExpenses" :key="costIndex"> | |||
| <text class="cell">{{ item.title }}</text> | |||
| <text class="cell">{{ item.num }}</text> | |||
| <text class="cell">{{ item.amount }}</text> | |||
| </view> | |||
| <view class="table-row" v-for="(item, costIndex) in record.exhibitRepairExpenseList" :key="costIndex"> | |||
| <text class="cell">{{ item.title }}</text> | |||
| <text class="cell">{{ item.num }}</text> | |||
| <text class="cell">{{ item.amount }}</text> | |||
| </view> | |||
| </view> | |||
| <!-- 维修记录特有字段 --> | |||
| <template v-if="activeMainTab === 'repair'"> | |||
| <!-- 问题是否解决 --> | |||
| <view class="info-row" > | |||
| <text class="label">问题是否解决</text> | |||
| <text class="value red-text">{{ record.isFix_dictText }}</text> | |||
| </view> | |||
| <!-- 备注 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">备注</text> | |||
| </view> | |||
| <!-- 备注文本区域 --> | |||
| <view class="content-text" v-if="!collapsedStates[index]"> | |||
| <text>{{ record.remark }}</text> | |||
| </view> | |||
| </template> | |||
| <!-- 保养记录特有字段 --> | |||
| <template v-else> | |||
| <!-- 附件信息 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">附件信息</text> | |||
| </view> | |||
| <!-- 附件信息文本区域 --> | |||
| <view class="content-text" v-if="!collapsedStates[index]"> | |||
| <text>{{ record.remarkText }}</text> | |||
| </view> | |||
| <!-- 附件图片 --> | |||
| <view class="image-container" v-if="!collapsedStates[index]"> | |||
| <image class="uploaded-image" v-for="(value, index) in record.remarkImage.split(',')" :src="value" :key="index" mode="aspectFill"></image> | |||
| </view> | |||
| <!-- 保养备注 --> | |||
| <view class="info-row" v-if="!collapsedStates[index]"> | |||
| <text class="label">备注</text> | |||
| </view> | |||
| <!-- 保养备注文本区域 --> | |||
| <view class="content-text" v-if="!collapsedStates[index]"> | |||
| <text>{{ record.remark }}</text> | |||
| </view> | |||
| </template> | |||
| <!-- 收起按钮 --> | |||
| <view class="collapse-btn" @click="toggleCollapse(index)"> | |||
| <text class="collapse-text">{{ collapsedStates[index] ? '查看全部' : '收起' }}</text> | |||
| <text class="collapse-icon">{{ collapsedStates[index] ? '▼' : '▲' }}</text> | |||
| </view> | |||
| </view> | |||
| <uv-loading-icon v-if="loading"></uv-loading-icon> | |||
| </view> | |||
| <view v-else-if="!loading && !records.length "> | |||
| <uv-empty icon="/static/暂无搜索结果.png" /> | |||
| </view> | |||
| <uv-loading-icon v-else></uv-loading-icon> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import ListMixin from '@/mixins/list' | |||
| export default { | |||
| mixins: [ListMixin], | |||
| data() { | |||
| return { | |||
| showpieceId: '', | |||
| mixinListApi: 'exhibit.queryRepairList', | |||
| activeMainTab: 'repair', // 当前激活的主Tab | |||
| activeFilter: 0, // 当前激活的筛选器 | |||
| collapsedStates: [], // 控制每个记录项的展开/收起状态 | |||
| afterUpdateDataFn(list) { | |||
| this.collapsedStates = new Array(list.length).fill(true) | |||
| }, | |||
| filterOptions: [ | |||
| { name: '时间' }, | |||
| { name: '人员' } | |||
| ], | |||
| selectedTime: '', // 选中的时间 | |||
| selectedPerson: '', // 选中的人员 | |||
| timeColumns: [ | |||
| ['今天', '昨天', '本周', '本月', '上月', '自定义'] | |||
| ], | |||
| personColumns: [ ] | |||
| } | |||
| }, | |||
| computed: { | |||
| contentText() { | |||
| const tabText = this.activeMainTab === 'repair' ? '维修' : '保养' | |||
| const filterText = this.filterOptions[this.activeFilter].name | |||
| let selectedText = '' | |||
| if (this.activeFilter === 0 && this.selectedTime) { | |||
| selectedText = ` - ${this.selectedTime}` | |||
| } else if (this.activeFilter === 1 && this.selectedPerson) { | |||
| selectedText = ` - ${this.selectedPerson}` | |||
| } | |||
| return `${tabText}记录 - 按${filterText}筛选${selectedText}` | |||
| } | |||
| }, | |||
| methods: { | |||
| mixinSetParams() { | |||
| const params = { } | |||
| if (this.activeMainTab === 'repair' && this.selectedTime) { | |||
| params.repairDate = this.selectedTime | |||
| } else if (this.activeMainTab === 'maintain' && this.selectedTime) { | |||
| params.maintainDate = this.selectedTime | |||
| } | |||
| if (this.selectedPerson) { | |||
| params.id = this.selectedPerson.id | |||
| } | |||
| return { | |||
| showpieceId: this.showpieceId, | |||
| ...params | |||
| } | |||
| }, | |||
| async switchMainTab(tab) { | |||
| this.activeMainTab = tab | |||
| this.mixinListApi = this.activeMainTab === 'repair' ? 'exhibit.queryRepairList' : 'exhibit.queryMaintenanceList' | |||
| this.onFilterChange() | |||
| this.initPage() | |||
| this.getList(true) | |||
| // this.initCollapsedStates() | |||
| }, | |||
| onFilterChange() { | |||
| // this.activeFilter = index | |||
| // 切换筛选器时清空选择 | |||
| this.selectedTime = '' | |||
| this.selectedPerson = '' | |||
| }, | |||
| showTimePicker() { | |||
| this.$refs.timePicker.open() | |||
| }, | |||
| showPersonPicker() { | |||
| this.$refs.personPicker.open() | |||
| }, | |||
| onTimeConfirm(e) { | |||
| this.selectedTime = this.$utils.formatTime(e.value) | |||
| this.initPage() | |||
| this.getList(true) | |||
| }, | |||
| onTimeCancel() { | |||
| console.log('取消选择时间') | |||
| }, | |||
| onPersonConfirm(value) { | |||
| this.selectedPerson = value.value[0] | |||
| console.log('选择的人员:', value) | |||
| this.initPage() | |||
| this.getList(true) | |||
| }, | |||
| onPersonCancel() { | |||
| console.log('取消选择人员') | |||
| }, | |||
| toggleCollapse(index) { | |||
| this.$set(this.collapsedStates, index, !this.collapsedStates[index]) | |||
| console.log('收起/展开费用详情', this.collapsedStates[index]) | |||
| } | |||
| }, | |||
| async onLoad(args){{ | |||
| this.showpieceId = args.id | |||
| const userRes = await this.$api.config.queryUserList() | |||
| this.personColumns = [[...userRes.result.records.map(item => ({ | |||
| label: item.nickName, | |||
| id: item.id | |||
| }))]] | |||
| }} | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .container { | |||
| background-color: #f5f5f5; | |||
| min-height: 100vh; | |||
| } | |||
| .header{ | |||
| padding: 16rpx 39rpx 23rpx; | |||
| background: #fff; | |||
| } | |||
| .main-tabs { | |||
| display: flex; | |||
| margin-bottom: 48rpx; | |||
| // border-bottom: 2rpx solid #f0f0f0; | |||
| .tab-item { | |||
| flex: 1; | |||
| position: relative; | |||
| padding: 13rpx 0; | |||
| text-align: center; | |||
| .tab-text { | |||
| font-size: 28rpx; | |||
| color: $secondary-text-color; | |||
| font-weight: 400; | |||
| transition: all 0.3s ease; | |||
| } | |||
| &.active { | |||
| .tab-text { | |||
| color: $primary-color; | |||
| // font-weight: 600; | |||
| } | |||
| } | |||
| .tab-underline { | |||
| position: absolute; | |||
| bottom: 0; | |||
| left: 50%; | |||
| transform: translateX(-50%); | |||
| width: 60rpx; | |||
| height: 4rpx; | |||
| background-color: $primary-color; | |||
| border-radius: 2rpx; | |||
| } | |||
| } | |||
| } | |||
| .filter-section { | |||
| margin-bottom: 32rpx; | |||
| } | |||
| .picker-buttons { | |||
| // margin-bottom: 32rpx; | |||
| display: flex; | |||
| gap: 55rpx; | |||
| .picker-btn { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: flex-start; | |||
| padding: 0; | |||
| background-color: transparent; | |||
| color: $primary-text-color; | |||
| &.active { | |||
| color: $primary-color; | |||
| } | |||
| .btn-text { | |||
| font-size: 28rpx; | |||
| // color: $primary-color; | |||
| margin-right: 10rpx; | |||
| } | |||
| .arrow-icon { | |||
| font-size: 20rpx; | |||
| // color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| .content-area { | |||
| padding: 22rpx 29rpx; | |||
| .loading-icon { | |||
| margin-top: 60rpx; | |||
| } | |||
| .record-item { | |||
| background: #fff; | |||
| border-radius: 16rpx; | |||
| padding: 29rpx; | |||
| margin-bottom: 37rpx; | |||
| border-radius: 15rpx; | |||
| box-shadow: 0 3rpx 6rpx 0rpx rgba(0,0,0,0.16); | |||
| .info-row { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: flex-start; | |||
| margin-bottom: 38rpx; | |||
| .label { | |||
| font-size: 28rpx; | |||
| color: $primary-text-color; | |||
| // font-weight: 400; | |||
| flex-shrink: 0; | |||
| } | |||
| .value { | |||
| font-size: 28rpx; | |||
| color: $primary-text-color; | |||
| text-align: right; | |||
| flex: 1; | |||
| margin-left: 32rpx; | |||
| &.red-text { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| .content-text { | |||
| background: #f5f5f5; | |||
| border-radius: 15rpx; | |||
| padding: 24rpx; | |||
| margin-bottom: 24rpx; | |||
| min-height: 120rpx; | |||
| text { | |||
| font-size: 28rpx; | |||
| color: $primary-text-color; | |||
| line-height: 1.5; | |||
| } | |||
| } | |||
| .image-container { | |||
| margin-bottom: 29rpx; | |||
| .uploaded-image { | |||
| width: 157rpx; | |||
| height: 157rpx; | |||
| // border-radius: 8rpx; | |||
| } | |||
| } | |||
| .cost-table { | |||
| margin-bottom: 24rpx; | |||
| .table-header { | |||
| display: flex; | |||
| // background: #f8f8f8; | |||
| // border-radius: 8rpx 8rpx 0 0; | |||
| padding: 30rpx 0; | |||
| justify-content: space-between; | |||
| .header-cell { | |||
| flex: 1; | |||
| font-size: 30rpx; | |||
| color: $secondary-text-color; | |||
| &:nth-child(1) { | |||
| text-align: left; | |||
| } | |||
| &:nth-child(2) { | |||
| text-align: center; | |||
| } | |||
| &:nth-child(3) { | |||
| text-align: right; | |||
| } | |||
| // font-weight: 500; | |||
| } | |||
| } | |||
| .table-row { | |||
| display: flex; | |||
| border-bottom: 1rpx solid #f0f0f0; | |||
| padding: 30rpx 0; | |||
| // justify-content: space-between; | |||
| .cell { | |||
| flex: 1; | |||
| font-size: 30rpx; | |||
| color: $primary-text-color; | |||
| &:nth-child(1) { | |||
| text-align: left; | |||
| } | |||
| &:nth-child(2) { | |||
| text-align: center; | |||
| } | |||
| &:nth-child(3) { | |||
| text-align: right; | |||
| } | |||
| } | |||
| // .cell:first-child { | |||
| // text-align: center; | |||
| // } | |||
| } | |||
| } | |||
| .view-all-btn { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| padding: 16rpx 0; | |||
| margin-top: 16rpx; | |||
| .view-all-text { | |||
| font-size: 26rpx; | |||
| color: $primary-color; | |||
| margin-right: 8rpx; | |||
| } | |||
| .view-all-icon { | |||
| font-size: 20rpx; | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| .collapse-btn { | |||
| display: flex; | |||
| justify-content: center; | |||
| align-items: center; | |||
| padding: 16rpx 0; | |||
| margin-top: 16rpx; | |||
| .collapse-text { | |||
| font-size: 26rpx; | |||
| color: $primary-color; | |||
| margin-right: 8rpx; | |||
| } | |||
| .collapse-icon { | |||
| font-size: 20rpx; | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -1,763 +0,0 @@ | |||
| <template> | |||
| <view class="maintenance-submit"> | |||
| <!-- 保养基本信息 --> | |||
| <view class="maintenance-info"> | |||
| <view class="info-header"> | |||
| <view class="red-line"></view> | |||
| <text class="info-title">保养项目</text> | |||
| </view> | |||
| <!-- 保养人 --> | |||
| <view class="form-item"> | |||
| <text class="label">保养人</text> | |||
| <view class="input-area" > | |||
| <input | |||
| v-model="maintenanceName" | |||
| placeholder="请填写" | |||
| class="input-field" | |||
| ref="maintainerInput" | |||
| /> | |||
| </view> | |||
| </view> | |||
| <!-- 保养日期 --> | |||
| <view class="form-item" @click="showDatePicker"> | |||
| <text class="label">保养日期</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !maintenanceDate }">{{ maintenanceDate || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 保养前状态 --> | |||
| <view class="form-item"> | |||
| <text class="label">保养前状态</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="stateFrontText" | |||
| placeholder="请填写保养前的设备内容" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 保养前图片 --> | |||
| <view class="image-upload"> | |||
| <view v-for="(img, index) in stateFrontImage" :key="index" class="image-item"> | |||
| <image :src="img" mode="aspectFill" @click="previewImage(img, stateFrontImage)"></image> | |||
| <view class="delete-btn" @click="deleteBeforeImage(index)"> | |||
| <uv-icon name="close" size="12" color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="upload-btn" @click="uploadBeforeImage"> | |||
| <uv-icon name="camera" size="34" color="#C70019"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 保养后状态 --> | |||
| <view class="form-item"> | |||
| <text class="label">保养后状态</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="stateBackText" | |||
| placeholder="请填写保养后的设备内容" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 保养后图片 --> | |||
| <view class="image-upload"> | |||
| <view v-for="(img, index) in stateBackImage" :key="index" class="image-item"> | |||
| <image :src="img" mode="aspectFill" @click="previewImage(img, stateBackImage)"></image> | |||
| <view class="delete-btn" @click="deleteAfterImage(index)"> | |||
| <uv-icon name="close" size="12" color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="upload-btn" @click="uploadAfterImage"> | |||
| <uv-icon name="camera" size="34" color="#C70019"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 是否产生费用 --> | |||
| <view class="form-item"> | |||
| <text class="label">是否产生费用</text> | |||
| <view class="radio-options"> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isExpend === '1' }" | |||
| @click="selectCost('1')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isExpend === '1' }"></view> | |||
| <text :class="{ active: isExpend === '1' }">是</text> | |||
| </view> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isExpend === '0' }" | |||
| @click="selectCost('0')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isExpend === '0' }"></view> | |||
| <text :class="{ active: isExpend === '0' }">否</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 产生费用 --> | |||
| <view class="form-item" v-if="isExpend === '1'"> | |||
| <text class="label">产生费用</text> | |||
| <view class="input-area" > | |||
| <input | |||
| v-model="amount" | |||
| placeholder="请输入费用" | |||
| disabled | |||
| class="input-field" | |||
| /> | |||
| </view> | |||
| </view> | |||
| <!-- 费用详情表格 --> | |||
| <view class="cost-table" v-if="isExpend === '1'"> | |||
| <view class="table-header"> | |||
| <text class="header-cell">费用名称</text> | |||
| <text class="header-cell">数量</text> | |||
| <text class="header-cell">金额</text> | |||
| <text class="header-cell"></text> | |||
| </view> | |||
| <view class="table-row" v-for="(item, index) in costList" :key="index"> | |||
| <view class="cell-input"> | |||
| <uv-input | |||
| v-model="item.name" | |||
| placeholder="费用名称" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }" | |||
| ></uv-input> | |||
| </view> | |||
| <view class="cell-input"> | |||
| <uv-input | |||
| v-model="item.quantity" | |||
| placeholder="数量" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }" | |||
| ></uv-input> | |||
| </view> | |||
| <view class="cell-input"> | |||
| <uv-input | |||
| v-model="item.amount" | |||
| placeholder="金额" | |||
| type="digit" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: 'transparent', fontSize: '28rpx' }" | |||
| ></uv-input> | |||
| </view> | |||
| <view class="cell-action"> | |||
| <view class="action-btn delete-btn" @click="removeCostItem(index)" v-if="costList.length > 1"> | |||
| <uv-icon name="close" size="14" color="#fff"></uv-icon> | |||
| </view> | |||
| <view class="action-btn add-btn" @click="addCostItem" v-if="index === costList.length - 1"> | |||
| <uv-icon name="plus" size="14" color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 附件信息 --> | |||
| <view class="form-item form-item-header"> | |||
| <text class="label active">附件信息</text> | |||
| </view> | |||
| <!-- 保养备注 --> | |||
| <view class="form-item"> | |||
| <text class="label">保养备注</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="remarkText" | |||
| placeholder="请填写备注" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 附件图片 --> | |||
| <view class="image-upload"> | |||
| <view v-for="(img, index) in remarkImage" :key="index" class="image-item"> | |||
| <image :src="img" mode="aspectFill" @click="previewImage(img, remarkImage)"></image> | |||
| <view class="delete-btn" @click="deleteAttachment(index)"> | |||
| <uv-icon name="close" size="12" color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="upload-btn" @click="uploadAttachment"> | |||
| <uv-icon name="camera" size="34" color="#C70019"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 下次保养日期 --> | |||
| <view class="form-item" @click="showNextDatePicker"> | |||
| <text class="label">下次保养日期</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !nextMaintenanceDate }">{{ nextMaintenanceDate || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 备注 --> | |||
| <view class="form-item"> | |||
| <text class="label">备注</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="remark" | |||
| placeholder="请填写备注" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| </view> | |||
| <!-- 提交按钮 --> | |||
| <view class="submit-container"> | |||
| <uv-button | |||
| type="primary" | |||
| text="立即提交" | |||
| :disabled="submiting" | |||
| :custom-style="{ backgroundColor: '#C70019', borderRadius: '25px' }" | |||
| @click="submitMaintenance" | |||
| ></uv-button> | |||
| </view> | |||
| <!-- 日期选择器 --> | |||
| <uv-datetime-picker | |||
| confirm-color="#C70019" | |||
| ref="datePicker" | |||
| mode="date" | |||
| v-model="timeValue" | |||
| @confirm="confirmDate" | |||
| ></uv-datetime-picker> | |||
| <uv-datetime-picker | |||
| confirm-color="#C70019" | |||
| ref="nextDatePicker" | |||
| mode="date" | |||
| v-model="nextTimeValue" | |||
| @confirm="confirmNextDate" | |||
| ></uv-datetime-picker> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| timeValue: Number(new Date()), | |||
| nextTimeValue: Number(new Date()), | |||
| // 表单数据 | |||
| maintenanceName: '', | |||
| maintenanceDate: '', | |||
| stateFrontText: '', | |||
| stateFrontImage: [], | |||
| stateBackText: '', | |||
| stateBackImage: [], | |||
| isExpend: '0', | |||
| costList: [{ name: '', quantity: '', amount: '' }], | |||
| remarkText: '', | |||
| remarkImage: [], | |||
| nextMaintenanceDate: '', | |||
| remark: '', | |||
| showpieceId: '', | |||
| submiting: false | |||
| } | |||
| }, | |||
| computed: { | |||
| // 计算总金额 | |||
| amount() { | |||
| return this.costList.reduce((sum, item) => { | |||
| return sum + (Number(item.quantity) * parseFloat(item.amount || 0)) | |||
| }, 0) | |||
| } | |||
| }, | |||
| methods: { | |||
| // 显示日期选择器 | |||
| showDatePicker() { | |||
| this.$refs.datePicker.open() | |||
| }, | |||
| // 确认日期 | |||
| confirmDate(e) { | |||
| // uv-datetime-picker返回的是时间戳,需要转换为日期格式 | |||
| this.maintenanceDate = this.$utils.formatTime(e.value) | |||
| }, | |||
| // 显示下次保养日期选择器 | |||
| showNextDatePicker() { | |||
| this.$refs.nextDatePicker.open() | |||
| }, | |||
| // 确认下次保养日期 | |||
| confirmNextDate(e) { | |||
| // uv-datetime-picker返回的是时间戳,需要转换为日期格式 | |||
| this.nextMaintenanceDate = this.$utils.formatTime(e.value) | |||
| }, | |||
| // 选择是否产生费用 | |||
| selectCost(value) { | |||
| this.isExpend = value | |||
| if (value === '0') { | |||
| this.costList = [{ name: '', quantity: '', amount: '' }] | |||
| } else if (this.costList.length === 0) { | |||
| this.costList = [{ name: '', quantity: '', amount: '' }] | |||
| } | |||
| }, | |||
| // 添加费用项目 | |||
| addCostItem() { | |||
| this.costList.push({ name: '', quantity: '', amount: '' }) | |||
| }, | |||
| // 删除费用项目 | |||
| removeCostItem(index) { | |||
| if (this.costList.length > 1) { | |||
| this.costList.splice(index, 1) | |||
| } else { | |||
| uni.showToast({ title: '至少保留一个费用项目', icon: 'none' }) | |||
| } | |||
| }, | |||
| // 上传保养前图片 | |||
| async uploadBeforeImage() { | |||
| try { | |||
| const result = await this.$utils.chooseAndUpload() | |||
| if (result && result.success) { | |||
| console.log(result); | |||
| this.stateFrontImage.push(result.url) | |||
| } | |||
| } catch (error) { | |||
| console.error('图片上传失败:', error) | |||
| uni.showToast({ | |||
| title: '图片上传失败', | |||
| icon: 'error' | |||
| }) | |||
| } | |||
| }, | |||
| // 删除保养前图片 | |||
| deleteBeforeImage(index) { | |||
| this.stateFrontImage.splice(index, 1) | |||
| }, | |||
| // 上传保养后图片 | |||
| async uploadAfterImage() { | |||
| try { | |||
| const result = await this.$utils.chooseAndUpload() | |||
| if (result && result.success) { | |||
| console.log(result); | |||
| this.stateBackImage.push(result.url) | |||
| } | |||
| } catch (error) { | |||
| console.error('头像上传失败:', error) | |||
| uni.showToast({ | |||
| title: '头像上传失败', | |||
| icon: 'error' | |||
| }) | |||
| } | |||
| }, | |||
| // 删除保养后图片 | |||
| deleteAfterImage(index) { | |||
| this.stateBackImage.splice(index, 1) | |||
| }, | |||
| // 上传附件 | |||
| async uploadAttachment() { | |||
| try { | |||
| const result = await this.$utils.chooseAndUpload() | |||
| if (result && result.success) { | |||
| console.log(result); | |||
| this.remarkImage.push(result.url) | |||
| } | |||
| } catch (error) { | |||
| console.error('头像上传失败:', error) | |||
| uni.showToast({ | |||
| title: '头像上传失败', | |||
| icon: 'error' | |||
| }) | |||
| } | |||
| }, | |||
| // 删除附件 | |||
| deleteAttachment(index) { | |||
| this.remarkImage.splice(index, 1) | |||
| }, | |||
| // 预览图片 | |||
| previewImage(url, imageList) { | |||
| uni.previewImage({ | |||
| urls: imageList, | |||
| current: url | |||
| }) | |||
| }, | |||
| // 提交保养 | |||
| async submitMaintenance() { | |||
| // 表单验证 | |||
| if (!this.maintenanceName.trim()) { | |||
| uni.showToast({ title: '请填写保养人', icon: 'none' }) | |||
| return | |||
| } | |||
| if (!this.stateFrontText.trim()) { | |||
| uni.showToast({ title: '请填写保养前状态', icon: 'none' }) | |||
| return | |||
| } | |||
| if (!this.stateBackText.trim()) { | |||
| uni.showToast({ title: '请填写保养后状态', icon: 'none' }) | |||
| return | |||
| } | |||
| if (this.isExpend === '1' && !this.amount){ | |||
| uni.showToast({ title: '请填写消费', icon: 'none' }) | |||
| return | |||
| } | |||
| // 把costList切换成字符串并用,,;分割 | |||
| // 提交数据 | |||
| const formData = { | |||
| maintenanceName: this.maintenanceName, | |||
| maintenanceDate: this.maintenanceDate, | |||
| stateFrontText: this.stateFrontText, | |||
| stateFrontImage: this.stateFrontImage?.join(',') || '', | |||
| stateBackText: this.stateBackText, | |||
| stateBackImage: this.stateBackImage?.join(',') || '', | |||
| expenseList: this.costList.map(item => { | |||
| return `${item.name},${item.quantity},${item.amount}` | |||
| }).join(';'), | |||
| isExpend: this.isExpend, | |||
| amount: this.amount, | |||
| remarkText: this.remarkText, | |||
| remarkImage: this.remarkImage?.join(',') || '', | |||
| nextMaintenanceDate: this.nextMaintenanceDate, | |||
| remark: this.remark, | |||
| showpieceId: this.showpieceId | |||
| } | |||
| this.submiting = true | |||
| try{ | |||
| const subRes = await this.$api.exhibit.addMaintenance(formData) | |||
| if(subRes.code == 200){ | |||
| uni.showToast({ title: subRes.message, icon: 'success' }) | |||
| // 返回上一页 | |||
| setTimeout(() => { | |||
| uni.navigateBack() | |||
| }, 1000) | |||
| }else{ | |||
| uni.showToast({ title: subRes.message, icon: 'none' }) | |||
| } | |||
| }catch(err){ | |||
| // uni.showToast({ title: err.message, icon: 'none' }) | |||
| this.submiting = false | |||
| } | |||
| } | |||
| }, | |||
| onLoad(options) { | |||
| this.showpieceId = options.id | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .maintenance-submit { | |||
| min-height: 100vh; | |||
| background-color: #f5f5f5; | |||
| padding-bottom: 200rpx; | |||
| } | |||
| .maintenance-info { | |||
| margin: 18rpx; | |||
| background: #ffffff; | |||
| border-radius: 15rpx; | |||
| box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16); | |||
| padding: 40rpx; | |||
| .info-header { | |||
| display: flex; | |||
| align-items: center; | |||
| margin-bottom: 40rpx; | |||
| .red-line { | |||
| width: 9rpx; | |||
| height: 33rpx; | |||
| background-color: $primary-color; | |||
| margin-right: 7rpx; | |||
| border-radius: 5rpx; | |||
| } | |||
| .info-title { | |||
| font-size: 30rpx; | |||
| font-weight: bold; | |||
| color: $primary-text-color; | |||
| } | |||
| } | |||
| .form-item-header { | |||
| border-bottom: none; | |||
| margin-top: 20rpx; | |||
| } | |||
| .form-item { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| padding: 24rpx 0; | |||
| border-bottom: 2rpx solid #f0f0f0; | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .label { | |||
| font-size: 30rpx; | |||
| color: $primary-text-color; | |||
| flex-shrink: 0; | |||
| &.active { | |||
| font-weight: bold; | |||
| } | |||
| } | |||
| .value { | |||
| font-size: 30rpx; | |||
| color: $secondary-text-color; | |||
| &.placeholder { | |||
| color: $secondary-text-color; | |||
| } | |||
| } | |||
| .select-area { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| } | |||
| .input-area { | |||
| flex: 1; | |||
| // background-color: #f5f5f5; | |||
| border-radius: 8rpx; | |||
| padding: 16rpx 24rpx; | |||
| margin-left: 24rpx; | |||
| .input-field { | |||
| width: 100%; | |||
| font-size: 30rpx; | |||
| color: $primary-text-color; | |||
| background: transparent; | |||
| border: none; | |||
| outline: none; | |||
| text-align: right; | |||
| &::placeholder { | |||
| color: $secondary-text-color; | |||
| } | |||
| } | |||
| } | |||
| .radio-options { | |||
| display: flex; | |||
| gap: 60rpx; | |||
| .radio-item { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| .radio-dot { | |||
| width: 32rpx; | |||
| height: 32rpx; | |||
| border: 4rpx solid #ddd; | |||
| border-radius: 50%; | |||
| position: relative; | |||
| &.active { | |||
| border-color: $primary-color; | |||
| &::after { | |||
| content: ''; | |||
| position: absolute; | |||
| top: 50%; | |||
| left: 50%; | |||
| transform: translate(-50%, -50%); | |||
| width: 16rpx; | |||
| height: 16rpx; | |||
| background-color: $primary-color; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| } | |||
| text { | |||
| font-size: 30rpx; | |||
| color: $secondary-text-color; | |||
| &.active { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .textarea-container { | |||
| border-radius: 8rpx; | |||
| } | |||
| .image-upload { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 24rpx; | |||
| margin: 16rpx 0; | |||
| .upload-btn { | |||
| width: 160rpx; | |||
| height: 160rpx; | |||
| border: 2rpx dashed $primary-color; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| background-color: #fff; | |||
| } | |||
| .image-item { | |||
| position: relative; | |||
| width: 160rpx; | |||
| height: 160rpx; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| border-radius: 8rpx; | |||
| } | |||
| .delete-btn { | |||
| position: absolute; | |||
| top: -12rpx; | |||
| right: -12rpx; | |||
| width: 40rpx; | |||
| height: 40rpx; | |||
| background-color: #ff4757; | |||
| border-radius: 50%; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| } | |||
| // 费用表格样式 | |||
| .cost-table { | |||
| margin-top: 24rpx; | |||
| border: 2rpx solid #f0f0f0; | |||
| border-radius: 8rpx; | |||
| overflow: hidden; | |||
| .table-header { | |||
| display: flex; | |||
| background-color: #f5f5f5; | |||
| padding: 16rpx 0; | |||
| .header-cell { | |||
| flex: 1; | |||
| text-align: center; | |||
| font-size: 28rpx; | |||
| font-weight: bold; | |||
| color: $primary-text-color; | |||
| &:first-child { | |||
| flex: 2; | |||
| } | |||
| &:last-child { | |||
| width: 120rpx; | |||
| flex: none; | |||
| } | |||
| } | |||
| } | |||
| .table-row { | |||
| display: flex; | |||
| border-top: 2rpx solid #f0f0f0; | |||
| .cell-input { | |||
| flex: 1; | |||
| padding: 8rpx; | |||
| border-right: 2rpx solid #f0f0f0; | |||
| &:first-child { | |||
| flex: 2; | |||
| } | |||
| &:last-child { | |||
| border-right: none; | |||
| } | |||
| } | |||
| .cell-action { | |||
| width: 120rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| gap: 8rpx; | |||
| padding: 8rpx; | |||
| .action-btn { | |||
| width: 36rpx; | |||
| height: 36rpx; | |||
| padding: 4rpx; | |||
| border-radius: 50%; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| &.add-btn { | |||
| background-color: #1a9c10; | |||
| } | |||
| &.delete-btn { | |||
| background-color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .submit-container { | |||
| position: fixed; | |||
| bottom: 0; | |||
| left: 0; | |||
| right: 0; | |||
| padding: 32rpx; | |||
| background-color: #fff; | |||
| border-top: 2rpx solid #f0f0f0; | |||
| } | |||
| </style> | |||
| @ -1,690 +0,0 @@ | |||
| <template> | |||
| <view class="repair-submit"> | |||
| <!-- 导航栏 --> | |||
| <!-- <uv-navbar title="报修提交" :border="false" bg-color="#ffffff" title-color="#333333" /> --> | |||
| <!-- 报修基本信息 --> | |||
| <view class="repair-info"> | |||
| <view class="info-header"> | |||
| <view class="red-line"></view> | |||
| <text class="info-title">报修基本信息</text> | |||
| </view> | |||
| <!-- 报修日期 --> | |||
| <view class="form-item" @click="showDatePicker"> | |||
| <text class="label">报修日期</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !malfunctionDate }">{{ malfunctionDate || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 故障紧急程度 --> | |||
| <view class="form-item " @click="showUrgencyPicker"> | |||
| <text class="label">故障紧急程度</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !urgency }">{{ urgency.label || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 故障情况 --> | |||
| <view class="form-item form-item-header"> | |||
| <text class="label active">故障情况</text> | |||
| </view> | |||
| <!-- 故障情况选择 --> | |||
| <view class="form-item" @click="showFaultPicker"> | |||
| <text class="label">故障情况</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !malfunctionStatus }">{{ malfunctionStatus || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 故障情况描述 --> | |||
| <view class="form-item"> | |||
| <text class="label">故障情况描述</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="malfunctionDesc" | |||
| placeholder="请对故障情况进行描述" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 故障图片 --> | |||
| <view class="form-item"> | |||
| <text class="label">故障图片</text> | |||
| </view> | |||
| <view class="image-upload"> | |||
| <view v-for="(img, index) in malfunctionImage" :key="index" class="image-item"> | |||
| <image :src="img" mode="aspectFill" @click="previewImage(img)"></image> | |||
| <view class="delete-btn" @click="deleteImage(index)"> | |||
| <uv-icon name="close" size="12" color="#fff"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <view class="upload-btn" @click="uploadImage"> | |||
| <uv-icon name="camera" size="34" color="#C70019"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 故障首次发生时间 --> | |||
| <view class="form-item" @click="showFirstOccurTimePicker"> | |||
| <text class="label">故障首次发生时间</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !firstDate }">{{ firstDate || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 发生频率 --> | |||
| <view class="form-item"> | |||
| <text class="label">发生频率</text> | |||
| <view class="radio-options"> | |||
| <view | |||
| v-for="(item, index) in frequencyOptions" | |||
| :key="index" | |||
| class="radio-item" | |||
| :class="{ active: frequency === item.value }" | |||
| @click="selectFrequency(item.value)" | |||
| > | |||
| <view class="radio-dot" :class="{ active: frequency === item.value }"></view> | |||
| <text :class="{ active: frequency === item.value }">{{ item.label }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 请描述与故障设备发生主要故障的具体条件 --> | |||
| <!-- <view class="form-item"> | |||
| <text class="label">请描述与故障设备发生主要故障的具体条件</text> | |||
| </view> --> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="reason" | |||
| placeholder="请填写说明故障发生频率的触发条件" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 是否影响使用 --> | |||
| <view class="form-item" @click="showImpactPicker"> | |||
| <text class="label">是否影响使用</text> | |||
| <view class="select-area"> | |||
| <text class="value" :class="{ placeholder: !isAffectUse }">{{ isAffectUse.label || '请选择' }}</text> | |||
| <uv-icon name="arrow-down" size="18" color="#000"></uv-icon> | |||
| </view> | |||
| </view> | |||
| <!-- 采取的临时措施 --> | |||
| <!-- 故障情况 --> | |||
| <view class="form-item form-item-header"> | |||
| <text class="label active">采取的临时措施</text> | |||
| </view> | |||
| <!-- <view class="form-item"> | |||
| <text class="label">是否采取临时措施</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="measureDesc" | |||
| placeholder="如有采取临时措施请填写措施说明" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> --> | |||
| <!-- 是否采取的对措施 --> | |||
| <view class="form-item"> | |||
| <text class="label">是否采取临时措施</text> | |||
| <view class="radio-options"> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isMeasure === '1' }" | |||
| @click="selectMeasures('1')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isMeasure === '1' }"></view> | |||
| <text :class="{ active: isMeasure === '1' }">是</text> | |||
| </view> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isMeasure === '0' }" | |||
| @click="selectMeasures('0')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isMeasure === '0' }"></view> | |||
| <text :class="{ active: isMeasure === '0' }">否</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="measureDesc" | |||
| placeholder="如有采取临时措施请填写措施说明" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| <!-- 是否影响体验 --> | |||
| <view class="form-item"> | |||
| <text class="label">是否影响体验</text> | |||
| <view class="radio-options"> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isAffectExperience === '1' }" | |||
| @click="selectExperience('1')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isAffectExperience === '1' }"></view> | |||
| <text :class="{ active: isAffectExperience === '1' }">是</text> | |||
| </view> | |||
| <view | |||
| class="radio-item" | |||
| :class="{ active: isAffectExperience === '0' }" | |||
| @click="selectExperience('0')" | |||
| > | |||
| <view class="radio-dot" :class="{ active: isAffectExperience === '0' }"></view> | |||
| <text :class="{ active: isAffectExperience === '0' }">否</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 备注 --> | |||
| <view class="form-item"> | |||
| <text class="label">备注</text> | |||
| </view> | |||
| <view class="textarea-container"> | |||
| <uv-textarea | |||
| v-model="remark" | |||
| placeholder="备注" | |||
| :maxlength="200" | |||
| :show-confirm-bar="false" | |||
| height="60" | |||
| border="none" | |||
| :custom-style="{ backgroundColor: '#f5f5f5' }" | |||
| ></uv-textarea> | |||
| </view> | |||
| </view> | |||
| <!-- 提交按钮 --> | |||
| <view class="submit-container"> | |||
| <uv-button | |||
| type="primary" | |||
| text="立即提交" | |||
| :custom-style="{ backgroundColor: '#C70019', borderRadius: '25px' }" | |||
| @click="submitRepair" | |||
| ></uv-button> | |||
| </view> | |||
| <!-- 选择器 --> | |||
| <uv-picker | |||
| confirm-color="#C70019" | |||
| ref="urgencyPicker" | |||
| :columns="urgencyColumns" | |||
| keyName="label" | |||
| @confirm="confirmUrgency" | |||
| @cancel="cancelUrgency" | |||
| ></uv-picker> | |||
| <uv-picker | |||
| confirm-color="#C70019" | |||
| ref="faultPicker" | |||
| :columns="faultColumns" | |||
| @confirm="confirmFault" | |||
| @cancel="cancelFault" | |||
| ></uv-picker> | |||
| <!-- 故障首次发生时间选择器 --> | |||
| <uv-datetime-picker | |||
| ref="firstOccurTimePicker" | |||
| mode="date" | |||
| v-model="firstTime" | |||
| confirm-color="#C70019" | |||
| @confirm="confirmFirstOccurTime" | |||
| ></uv-datetime-picker> | |||
| <uv-picker | |||
| confirm-color="#C70019" | |||
| ref="impactPicker" | |||
| :columns="impactColumns" | |||
| @confirm="confirmImpact" | |||
| @cancel="cancelImpact" | |||
| keyName="label" | |||
| ></uv-picker> | |||
| <!-- 日期选择器 --> | |||
| <uv-datetime-picker | |||
| confirm-color="#C70019" | |||
| ref="datePicker" | |||
| v-model="timeValue" | |||
| mode="date" | |||
| @confirm="confirmDate" | |||
| ></uv-datetime-picker> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| // 表单数据 | |||
| malfunctionDate: '', | |||
| urgency: '', | |||
| malfunctionStatus: '', | |||
| malfunctionDesc: '', | |||
| malfunctionImage: [], | |||
| firstDate: '', | |||
| frequency: '1', | |||
| reason: '', | |||
| isAffectUse: '0', | |||
| measureDesc: '', | |||
| isMeasure: '0', | |||
| isAffectExperience: '0', | |||
| remark: '', | |||
| showpieceId: '', | |||
| timeValue: Number(new Date()), | |||
| firstTime: Number(new Date()), | |||
| // 频率选项 | |||
| frequencyOptions: [ | |||
| { label: '持续性问题', value: '0' }, | |||
| { label: '间歇性问题', value: '1' } | |||
| ], | |||
| // 选择器数据 | |||
| urgencyColumns: [ | |||
| [ | |||
| { label: '一般', value: '0' }, | |||
| { label: '紧急', value: '1'} | |||
| ] | |||
| ], | |||
| faultColumns: [['硬件故障', '软件故障', '网络故障', '其他']], | |||
| impactColumns: [[ | |||
| { label: '是', value: '1' }, | |||
| { label: '否', value: '0' } | |||
| ]], | |||
| } | |||
| }, | |||
| methods: { | |||
| // 显示日期选择器 | |||
| showDatePicker() { | |||
| this.$refs.datePicker.open() | |||
| }, | |||
| // 确认日期选择 | |||
| confirmDate(e) { | |||
| this.malfunctionDate = this.$utils.formatTime(e.value) | |||
| }, | |||
| // 显示紧急程度选择器 | |||
| showUrgencyPicker() { | |||
| this.$refs.urgencyPicker.open() | |||
| }, | |||
| // 确认紧急程度 | |||
| confirmUrgency(e) { | |||
| this.urgency = e.value[0] | |||
| }, | |||
| // 取消紧急程度选择 | |||
| cancelUrgency() { | |||
| // 取消操作 | |||
| }, | |||
| // 显示故障情况选择器 | |||
| showFaultPicker() { | |||
| this.$refs.faultPicker.open() | |||
| }, | |||
| // 确认故障情况 | |||
| confirmFault(e) { | |||
| this.malfunctionStatus = e.value[0] | |||
| }, | |||
| // 取消故障情况选择 | |||
| cancelFault() { | |||
| // 取消操作 | |||
| }, | |||
| // 显示故障首次发生时间选择器 | |||
| showFirstOccurTimePicker() { | |||
| this.$refs.firstOccurTimePicker.open() | |||
| }, | |||
| // 确认故障首次发生时间 | |||
| confirmFirstOccurTime(e) { | |||
| this.firstDate = this.$utils.formatTime(e.value) | |||
| }, | |||
| // 显示影响使用选择器 | |||
| showImpactPicker() { | |||
| this.$refs.impactPicker.open() | |||
| }, | |||
| // 确认影响使用 | |||
| confirmImpact(e) { | |||
| this.isAffectUse = e.value[0] | |||
| }, | |||
| // 取消影响使用选择 | |||
| cancelImpact() { | |||
| // 取消操作 | |||
| }, | |||
| // 选择频率 | |||
| selectFrequency(value) { | |||
| this.frequency = value | |||
| }, | |||
| // 选择是否采取措施 | |||
| selectMeasures(value) { | |||
| this.isMeasure = value | |||
| }, | |||
| // 选择是否影响体验 | |||
| selectExperience(value) { | |||
| this.isAffectExperience = value | |||
| }, | |||
| // 上传图片 | |||
| async uploadImage() { | |||
| try { | |||
| const result = await this.$utils.chooseAndUpload() | |||
| if (result && result.success) { | |||
| console.log(result); | |||
| this.malfunctionImage.push(result.url) | |||
| } | |||
| } catch (error) { | |||
| console.error('头像上传失败:', error) | |||
| uni.showToast({ | |||
| title: '头像上传失败', | |||
| icon: 'error' | |||
| }) | |||
| } | |||
| }, | |||
| // 删除图片 | |||
| deleteImage(index) { | |||
| this.malfunctionImage.splice(index, 1) | |||
| }, | |||
| // 预览图片 | |||
| previewImage(url) { | |||
| uni.previewImage({ | |||
| urls: this.malfunctionImage, | |||
| current: url | |||
| }) | |||
| }, | |||
| // 提交报修 | |||
| async submitRepair() { | |||
| // 表单验证 | |||
| if (!this.urgency) { | |||
| uni.showToast({ title: '请选择故障紧急程度', icon: 'none' }) | |||
| return | |||
| } | |||
| if (!this.malfunctionImage.length) { | |||
| uni.showToast({ title: '请上传故障图片', icon: 'none' }) | |||
| return | |||
| } | |||
| if (!this.malfunctionDesc.trim()) { | |||
| uni.showToast({ title: '请填写故障情况描述', icon: 'none' }) | |||
| return | |||
| } | |||
| if (!this.firstDate.trim()) { | |||
| uni.showToast({ title: '请选择故障首次发生时间', icon: 'none' }) | |||
| return | |||
| } | |||
| // 提交数据 | |||
| const formData = { | |||
| showpieceId: this.showpieceId, | |||
| malfunctionDate: this.malfunctionDate, | |||
| urgency: this.urgency.value, | |||
| malfunctionDesc: this.malfunctionStatus + this.malfunctionDesc, | |||
| malfunctionImage: this.malfunctionImage.join(','), | |||
| firstDate: this.firstDate, | |||
| frequency: this.frequency, | |||
| reason: this.reason, | |||
| isAffectUse: this.isAffectUse.value, | |||
| measureDesc: this.measureDesc, | |||
| isMeasure: this.isMeasure, | |||
| isAffectExperience: this.isAffectExperience, | |||
| remark: this.remark | |||
| } | |||
| // console.log('提交数据:', formData) | |||
| // uni.showToast({ title: '提交成功', icon: 'success' }) | |||
| const subRes = await this.$api.exhibit.addMalfunction({...formData}) | |||
| if (subRes.code === 200) { | |||
| uni.showToast({ title: subRes.message}) | |||
| setTimeout(() => { | |||
| uni.navigateBack() | |||
| }, 1000) | |||
| }else{ | |||
| uni.showToast({ title: subRes.message, icon: 'none' }) | |||
| } | |||
| } | |||
| }, | |||
| async onLoad(args) { | |||
| this.showpieceId = args.id | |||
| try { | |||
| const listRes = await this.$api.config.queryMalfunctionDescList() | |||
| if (listRes.code === 200) { | |||
| this.faultColumns = [[...listRes.result.records.map(item => item.malfunction)]] | |||
| } | |||
| } catch (error) { | |||
| uni.showToast({ title: error.message, icon: 'none' }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .repair-submit { | |||
| min-height: 100vh; | |||
| background-color: #f5f5f5; | |||
| padding-bottom: 200rpx; | |||
| } | |||
| .repair-info { | |||
| margin: 18rpx; | |||
| background: #ffffff; | |||
| border-radius: 15rpx; | |||
| box-shadow: 0rpx 3rpx 6rpx 0rpx rgba(0,0,0,0.16); | |||
| padding: 40rpx; | |||
| .info-header { | |||
| display: flex; | |||
| align-items: center; | |||
| margin-bottom: 40rpx; | |||
| .red-line { | |||
| width: 9rpx; | |||
| height: 33rpx; | |||
| background-color: $primary-color; | |||
| margin-right: 7rpx; | |||
| border-radius: 5rpx; | |||
| } | |||
| .info-title { | |||
| font-size: 30rpx; | |||
| font-weight: bold; | |||
| color: $primary-text-color; | |||
| } | |||
| } | |||
| .form-item-header { | |||
| border-bottom: none; | |||
| margin-top: 20rpx; | |||
| } | |||
| .form-item { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| padding: 24rpx 0; | |||
| border-bottom: 2rpx solid #f0f0f0; | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .label { | |||
| font-size: 30rpx; | |||
| color: $primary-text-color; | |||
| flex-shrink: 0; | |||
| &.active { | |||
| font-weight: bold; | |||
| } | |||
| } | |||
| .value { | |||
| font-size: 30rpx; | |||
| color: $secondary-text-color; | |||
| &.placeholder { | |||
| color: $secondary-text-color; | |||
| } | |||
| } | |||
| .select-area { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| } | |||
| } | |||
| .textarea-container { | |||
| // margin: 16rpx 0 32rpx 0; | |||
| // background-color: #f5f5f5; | |||
| border-radius: 8rpx; | |||
| // padding: 16rpx; | |||
| } | |||
| .image-upload { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 24rpx; | |||
| margin: 16rpx 0; | |||
| .upload-btn { | |||
| width: 160rpx; | |||
| height: 160rpx; | |||
| border: 2rpx dashed $primary-color; | |||
| // border-radius: 8rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| background-color: #fff; | |||
| } | |||
| .image-item { | |||
| position: relative; | |||
| width: 160rpx; | |||
| height: 160rpx; | |||
| image { | |||
| width: 100%; | |||
| height: 100%; | |||
| border-radius: 8rpx; | |||
| } | |||
| .delete-btn { | |||
| position: absolute; | |||
| top: -12rpx; | |||
| right: -12rpx; | |||
| width: 40rpx; | |||
| height: 40rpx; | |||
| background-color: #ff4757; | |||
| border-radius: 50%; | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: center; | |||
| } | |||
| } | |||
| } | |||
| .hint-text { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| margin-top: 16rpx; | |||
| } | |||
| .form-item .radio-options { | |||
| display: flex; | |||
| gap: 60rpx; | |||
| .radio-item { | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| .radio-dot { | |||
| width: 32rpx; | |||
| height: 32rpx; | |||
| border: 4rpx solid #ddd; | |||
| border-radius: 50%; | |||
| position: relative; | |||
| &.active { | |||
| border-color: $primary-color; | |||
| color: $primary-color; | |||
| &::after { | |||
| content: ''; | |||
| position: absolute; | |||
| top: 50%; | |||
| left: 50%; | |||
| transform: translate(-50%, -50%); | |||
| width: 16rpx; | |||
| height: 16rpx; | |||
| background-color: $primary-color; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| } | |||
| text { | |||
| font-size: 30rpx; | |||
| color: $secondary-text-color; | |||
| &.active { | |||
| color: $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| .submit-container { | |||
| position: fixed; | |||
| bottom: 0; | |||
| left: 0; | |||
| right: 0; | |||
| padding: 32rpx; | |||
| background-color: #fff; | |||
| border-top: 2rpx solid #f0f0f0; | |||
| } | |||
| </style> | |||
| @ -0,0 +1,187 @@ | |||
| <template> | |||
| <view class="cash-page"> | |||
| <!-- 顶部标题栏 --> | |||
| <!-- 表单内容 --> | |||
| <view class="form-container"> | |||
| <view class="header"> | |||
| <view class="title">微信提现</view> | |||
| <view class="flow-link">过往流水 ></view> | |||
| </view> | |||
| <!-- 真实姓名 --> | |||
| <view class="form-item"> | |||
| <view class="label">真实姓名</view> | |||
| <uv-input | |||
| v-model="realName" | |||
| placeholder="请输入" | |||
| border="none" | |||
| :custom-style="inputStyle" | |||
| ></uv-input> | |||
| </view> | |||
| <!-- 提现金额 --> | |||
| <view class="form-item"> | |||
| <view class="label">提现金额</view> | |||
| <uv-input | |||
| v-model="amount" | |||
| placeholder="请输入" | |||
| type="number" | |||
| border="none" | |||
| :custom-style="inputStyle" | |||
| ></uv-input> | |||
| </view> | |||
| </view> | |||
| <!-- 说明文字 --> | |||
| <view class="notice-text"> | |||
| 请仔细检查并确认相关信息,因用户个人疏忽导致的充值错误,需由用户自行承担。 | |||
| <text class="link-text" @click="showWithdrawRules">《提现须知》</text> | |||
| </view> | |||
| <!-- 固定底部按钮 --> | |||
| <view class="fixed-bottom"> | |||
| <uv-button | |||
| type="primary" | |||
| :custom-style="buttonStyle" | |||
| @click="handleWithdraw" | |||
| > | |||
| 提现 | |||
| </uv-button> | |||
| <uv-safe-bottom></uv-safe-bottom> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| realName: '', | |||
| amount: '', | |||
| inputStyle: { | |||
| backgroundColor: 'transparent', | |||
| fontSize: '32rpx', | |||
| color: '#333' | |||
| }, | |||
| buttonStyle: { | |||
| backgroundColor: '#22F2EB', | |||
| borderRadius: '50rpx', | |||
| height: '88rpx', | |||
| fontSize: '32rpx', | |||
| fontWeight: 'bold' | |||
| } | |||
| } | |||
| }, | |||
| methods: { | |||
| handleWithdraw() { | |||
| if (!this.realName) { | |||
| uni.showToast({ | |||
| title: '请输入真实姓名', | |||
| icon: 'none' | |||
| }) | |||
| return | |||
| } | |||
| if (!this.amount) { | |||
| uni.showToast({ | |||
| title: '请输入提现金额', | |||
| icon: 'none' | |||
| }) | |||
| return | |||
| } | |||
| // 提现逻辑 | |||
| console.log('提现信息:', { | |||
| realName: this.realName, | |||
| amount: this.amount | |||
| }) | |||
| uni.showToast({ | |||
| title: '提现申请已提交', | |||
| icon: 'success' | |||
| }) | |||
| }, | |||
| showWithdrawRules() { | |||
| // 显示提现须知 | |||
| uni.showModal({ | |||
| title: '提现须知', | |||
| content: '1. 提现金额最低10元\n2. 工作日24小时内到账\n3. 手续费按平台规定收取', | |||
| showCancel: false | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| // @import '@/uni.scss'; | |||
| .cash-page { | |||
| min-height: 100vh; | |||
| background-color: #F2F2F2; | |||
| padding-bottom: 200rpx; | |||
| padding-top: 40rpx; | |||
| .header { | |||
| background-color: #fff; | |||
| padding: 40rpx 40rpx 30rpx; | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| .title { | |||
| font-size: 36rpx; | |||
| font-weight: bold; | |||
| color: #333; | |||
| } | |||
| .flow-link { | |||
| font-size: 28rpx; | |||
| color: #999; | |||
| } | |||
| } | |||
| .form-container { | |||
| background-color: #fff; | |||
| margin: 20rpx 40rpx; | |||
| border-radius: 32rpx; | |||
| margin-top: 20rpx; | |||
| .form-item { | |||
| padding: 40rpx; | |||
| border-bottom: 1rpx solid #f0f0f0; | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .label { | |||
| font-size: 32rpx; | |||
| color: #333; | |||
| margin-bottom: 20rpx; | |||
| font-weight: 500; | |||
| } | |||
| } | |||
| } | |||
| .notice-text { | |||
| padding: 40rpx; | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| line-height: 1.6; | |||
| .link-text { | |||
| color: #22F2EB; | |||
| } | |||
| } | |||
| .fixed-bottom { | |||
| position: fixed; | |||
| bottom: 0; | |||
| left: 0; | |||
| right: 0; | |||
| padding: 30rpx 40rpx; | |||
| background-color: #fff; | |||
| border-top: 1rpx solid #f0f0f0; | |||
| z-index: 999; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,300 @@ | |||
| <template> | |||
| <view class="discount-container"> | |||
| <!-- 顶部tab切换 --> | |||
| <uv-subsection | |||
| :list="tabList" | |||
| :current="currentTab" | |||
| @change="onTabChange" | |||
| :activeColor="tabStyle.activeColor" | |||
| :inactiveColor="tabStyle.inactiveColor" | |||
| :bgColor="tabStyle.bgColor" | |||
| :fontSize="tabStyle.fontSize" | |||
| :height="tabStyle.height" | |||
| ></uv-subsection> | |||
| <!-- 优惠券列表 --> | |||
| <view class="coupon-list"> | |||
| <view | |||
| v-for="(coupon, index) in currentCoupons" | |||
| :key="index" | |||
| class="coupon-item" | |||
| :class="{ | |||
| 'used-coupon': coupon.status === 'used', | |||
| 'expired-coupon': coupon.status === 'expired' | |||
| }" | |||
| > | |||
| <!-- 左侧金额区域 --> | |||
| <view class="coupon-left"> | |||
| <text class="coupon-symbol">¥</text> | |||
| <text class="coupon-amount">{{ coupon.amount }}</text> | |||
| <!-- 状态盖章 --> | |||
| <image | |||
| v-if="coupon.status !== 'available'" | |||
| class="status-stamp" | |||
| :src="coupon.status === 'used' ? '/static/已使用盖章.png' : '/static/已过期盖章.png'" | |||
| mode="aspectFit" | |||
| ></image> | |||
| </view> | |||
| <!-- 右侧信息区域 --> | |||
| <view class="coupon-right"> | |||
| <view class="coupon-title">{{ coupon.title }}</view> | |||
| <view class="coupon-expire">有效期至 {{ coupon.expireDate }}</view> | |||
| <!-- 使用按钮或状态 --> | |||
| <view class="coupon-action"> | |||
| <uv-button | |||
| v-if="coupon.status === 'available'" | |||
| :customStyle="buttonStyle" | |||
| text="去使用" | |||
| @click="useCoupon(coupon)" | |||
| ></uv-button> | |||
| <view | |||
| v-else | |||
| class="coupon-status" | |||
| :class="{ | |||
| 'used-status': coupon.status === 'used', | |||
| 'expired-status': coupon.status === 'expired' | |||
| }" | |||
| > | |||
| {{ coupon.status === 'used' ? '已使用' : '已过期' }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 空状态 --> | |||
| <uv-empty | |||
| v-if="currentCoupons.length === 0" | |||
| text="暂无优惠券" | |||
| :textColor="emptyStyle.textColor" | |||
| :textSize="emptyStyle.textSize" | |||
| :marginTop="emptyStyle.marginTop" | |||
| ></uv-empty> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| currentTab: 0, | |||
| tabList: [ | |||
| { name: '待使用' }, | |||
| { name: '已使用' }, | |||
| { name: '已过期' } | |||
| ], | |||
| // tab样式配置 | |||
| tabStyle: { | |||
| activeColor: '#06DADC', | |||
| inactiveColor: '#999', | |||
| bgColor: '#f8f8f8', | |||
| fontSize: '28rpx', | |||
| height: '80rpx' | |||
| }, | |||
| // 按钮样式配置 | |||
| buttonStyle: { | |||
| backgroundColor: '#06DADC', | |||
| borderRadius: '99rpx', | |||
| width: '140rpx', | |||
| height: '60rpx', | |||
| fontSize: '30rpx', | |||
| color: '#fff' | |||
| }, | |||
| // 空状态样式配置 | |||
| emptyStyle: { | |||
| textColor: '#999', | |||
| textSize: '28rpx', | |||
| marginTop: '200rpx' | |||
| }, | |||
| // 优惠券数据 | |||
| coupons: { | |||
| available: [ | |||
| { | |||
| id: 1, | |||
| title: '专属福利】20元红包', | |||
| amount: 20, | |||
| expireDate: '2026-04-28', | |||
| status: 'available' | |||
| }, | |||
| { | |||
| id: 2, | |||
| title: '专属福利】400元红包', | |||
| amount: 400, | |||
| expireDate: '2026-04-28', | |||
| status: 'available' | |||
| }, | |||
| { | |||
| id: 3, | |||
| title: '专属福利】400元红包', | |||
| amount: 400, | |||
| expireDate: '2026-04-28', | |||
| status: 'available' | |||
| } | |||
| ], | |||
| used: [ | |||
| { | |||
| id: 4, | |||
| title: '专属福利】20元红包', | |||
| amount: 20, | |||
| expireDate: '2026-04-28', | |||
| status: 'used' | |||
| } | |||
| ], | |||
| expired: [ | |||
| { | |||
| id: 5, | |||
| title: '专属福利】20元红包', | |||
| amount: 20, | |||
| expireDate: '2026-04-28', | |||
| status: 'expired' | |||
| } | |||
| ] | |||
| } | |||
| } | |||
| }, | |||
| computed: { | |||
| currentCoupons() { | |||
| const statusMap = ['available', 'used', 'expired'] | |||
| return this.coupons[statusMap[this.currentTab]] || [] | |||
| } | |||
| }, | |||
| methods: { | |||
| onTabChange(index) { | |||
| this.currentTab = index | |||
| }, | |||
| useCoupon(coupon) { | |||
| uni.showToast({ | |||
| title: '跳转到使用页面', | |||
| icon: 'none' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .discount-container { | |||
| min-height: 100vh; | |||
| background-color: #f8f8f8; | |||
| .coupon-list { | |||
| padding: 40rpx 30rpx; | |||
| .coupon-item { | |||
| display: flex; | |||
| background-color: #fff; | |||
| border-radius: 24rpx; | |||
| margin-bottom: 24rpx; | |||
| overflow: hidden; | |||
| position: relative; | |||
| padding: 8rpx; | |||
| // box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08); | |||
| &.used-coupon, | |||
| &.expired-coupon { | |||
| .coupon-left { | |||
| background-color: #E3E3E3; | |||
| .coupon-symbol, | |||
| .coupon-amount { | |||
| color: #FBFBFB; | |||
| } | |||
| } | |||
| } | |||
| .coupon-left { | |||
| width: 180rpx; | |||
| background-color: #FFF2F2; | |||
| display: flex; | |||
| // flex-direction: column; | |||
| align-items: center; | |||
| justify-content: center; | |||
| border-radius: 16rpx; | |||
| position: relative; | |||
| .coupon-symbol { | |||
| font-size: 24rpx; | |||
| color: #FF4800; | |||
| font-weight: bold; | |||
| margin-bottom: 10rpx; | |||
| } | |||
| .coupon-amount { | |||
| font-size: 48rpx; | |||
| color: #FF4800; | |||
| font-weight: 500; | |||
| line-height: 1.4; | |||
| } | |||
| .status-stamp { | |||
| position: absolute; | |||
| bottom: 0rpx; | |||
| right: 0rpx; | |||
| width: 100rpx; | |||
| height: 100rpx; | |||
| // opacity: 0.8; | |||
| } | |||
| } | |||
| .coupon-right { | |||
| flex: 1; | |||
| margin-left: 20rpx; | |||
| padding: 40rpx 30rpx 20rpx; | |||
| position: relative; | |||
| width: 0px; | |||
| border-left: 2rpx dashed #DADADA; | |||
| .coupon-title { | |||
| font-size: 32rpx; | |||
| color: #181818; | |||
| font-weight: bold; | |||
| margin-bottom: 16rpx; | |||
| } | |||
| .coupon-expire { | |||
| font-size: 28rpx; | |||
| color: #9B9B9B; | |||
| margin-bottom: 16rpx; | |||
| } | |||
| .coupon-action { | |||
| display: flex; | |||
| justify-content: flex-start; | |||
| .coupon-status { | |||
| padding: 10rpx 30rpx; | |||
| border-radius: 40rpx; | |||
| font-size: 30rpx; | |||
| text-align: center; | |||
| &.used-status { | |||
| background-color: #E3E3E3; | |||
| color: #fff; | |||
| } | |||
| &.expired-status { | |||
| background-color: #E3E3E3; | |||
| color: #fff; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,31 @@ | |||
| <template> | |||
| <view class="container"> | |||
| <view class="body"> | |||
| <rich-text :nodes="htmlContent"></rich-text> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script > | |||
| export default { | |||
| data() { | |||
| return { | |||
| htmlContent: '<h1>这是一个标题</h1><p>这是一个段落</p>' | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .container { | |||
| min-height: 100vh; | |||
| background-color: #F7F8FA; | |||
| .body{ | |||
| border-radius: 32rpx; | |||
| padding: 32rpx; | |||
| margin: 40rpx; | |||
| background: #fff; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,31 @@ | |||
| <template> | |||
| <view class="container"> | |||
| <view class="body"> | |||
| <rich-text :nodes="htmlContent"></rich-text> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script > | |||
| export default { | |||
| data() { | |||
| return { | |||
| htmlContent: '<h1>这是一个标题</h1><p>这是一个段落</p>' | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .container { | |||
| min-height: 100vh; | |||
| background-color: #F7F8FA; | |||
| .body{ | |||
| border-radius: 32rpx; | |||
| padding: 32rpx; | |||
| margin: 40rpx; | |||
| background: #fff; | |||
| } | |||
| } | |||
| </style> | |||
| @ -0,0 +1,448 @@ | |||
| <template> | |||
| <view class="promote-page"> | |||
| <uv-status-bar></uv-status-bar> | |||
| <!-- 主要内容区域 --> | |||
| <view class="content"> | |||
| <!-- 推广官图片 --> | |||
| <view class="promote-image-container"> | |||
| <uv-icon name="arrow-left" size="20" color="black" @click="goBack"></uv-icon> | |||
| <view :style="{flex: 1, justifyContent: 'center', display: 'flex'}"> | |||
| <image | |||
| class="promote-image" | |||
| src="/static/推广官.png" | |||
| mode="widthFix" | |||
| ></image> | |||
| </view> | |||
| </view> | |||
| <!-- 推广标语图片 --> | |||
| <view class="slogan-container"> | |||
| <image | |||
| class="slogan-image" | |||
| src="/static/推广标语.png" | |||
| mode="widthFix" | |||
| ></image> | |||
| </view> | |||
| </view> | |||
| <!-- 外部大容器 --> | |||
| <view class="main-container"> | |||
| <!-- 个人信息容器 --> | |||
| <view class="profile-container"> | |||
| <image class="profile-avatar" src="/static/待上传头像.png" mode="aspectFill"></image> | |||
| <view class="profile-info"> | |||
| <text class="profile-name">战斗世界</text> | |||
| <text class="profile-id">ID: 5625354</text> | |||
| </view> | |||
| <view class="profile-stats"> | |||
| <view class="stat-item"> | |||
| <text class="stat-number">888</text> | |||
| <text class="stat-label">推广人数</text> | |||
| </view> | |||
| <view class="stat-item"> | |||
| <text class="stat-number">341</text> | |||
| <text class="stat-label">总佣金</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 功能按钮区域 --> | |||
| <view class="function-buttons"> | |||
| <view class="function-item" @click="goTeam"> | |||
| <image class="function-icon" src="/static/团队图标.png" mode="aspectFit"></image> | |||
| <text class="function-text">我的团队</text> | |||
| </view> | |||
| <view class="function-item"> | |||
| <image class="function-icon" src="/static/二维码图标.png" mode="aspectFit"></image> | |||
| <text class="function-text">我的二维码</text> | |||
| </view> | |||
| <view class="function-item" @click="goCash"> | |||
| <image class="function-icon" src="/static/提现图标.png" mode="aspectFit"></image> | |||
| <text class="function-text">提现</text> | |||
| </view> | |||
| </view> | |||
| <!-- 余额显示 --> | |||
| <view class="balance-section"> | |||
| <text class="balance-label">余额</text> | |||
| <text class="balance-amount">¥88.32</text> | |||
| <uv-icon name="arrow-right" size="16" color="#999"></uv-icon> | |||
| </view> | |||
| <!-- 转账记录容器 --> | |||
| <view class="record-container"> | |||
| <view class="record-list"> | |||
| <view class="record-item" v-for="(item, index) in recordList" :key="index"> | |||
| <view class="record-avatar"> | |||
| <image class="avatar" :src="item.avatar" mode="aspectFill"></image> | |||
| <text class="avatar-name">{{ item.avatarName }}</text> | |||
| </view> | |||
| <view class="record-info"> | |||
| <text class="record-title">{{ item.title }}</text> | |||
| <text class="record-date">{{ item.date }}</text> | |||
| </view> | |||
| <view class="record-amount"> | |||
| <text class="amount">{{ item.amount }}</text> | |||
| <text class="status" :class="item.statusClass">{{ item.status }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| <!-- 底部固定按钮 --> | |||
| <view class="bottom-button-container"> | |||
| <uv-button :custom-style="{ | |||
| height: '82rpx', | |||
| borderRadius: '198rpx', | |||
| background: '#06DADC', | |||
| border: '2rpx solid #06DADC', | |||
| lineHeight: '82rpx', | |||
| fontSize: '36rpx' | |||
| }" type="primary">分享</uv-button> | |||
| <uv-safe-bottom></uv-safe-bottom> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| recordList: [ | |||
| { | |||
| avatar: '/static/待上传头像.png', | |||
| title: '分享提成获得奖励', | |||
| date: '2025-03-18', | |||
| amount: '+5', | |||
| status: '已领取,微信打款', | |||
| statusClass: 'status-received', | |||
| avatarName: '战斗世界' | |||
| }, | |||
| { | |||
| avatar: '/static/待上传头像.png', | |||
| title: '分享提成获得奖励', | |||
| date: '2025-03-18', | |||
| amount: '+5', | |||
| status: '领取', | |||
| statusClass: 'status-available', | |||
| avatarName: '战斗世界' | |||
| }, | |||
| { | |||
| avatar: '/static/待上传头像.png', | |||
| title: '分享提成获得奖励', | |||
| date: '2025-03-18', | |||
| amount: '+5', | |||
| status: '已领取,线下打款', | |||
| statusClass: 'status-received', | |||
| avatarName: '战斗世界' | |||
| }, | |||
| { | |||
| avatar: '/static/待上传头像.png', | |||
| title: '分享提成获得奖励', | |||
| date: '2025-03-18', | |||
| amount: '+5', | |||
| status: '领取', | |||
| statusClass: 'status-available', | |||
| avatarName: '战斗世界' | |||
| }, | |||
| { | |||
| avatar: '/static/待上传头像.png', | |||
| title: '分享提成获得奖励', | |||
| date: '2025-03-18', | |||
| amount: '+5', | |||
| status: '领取', | |||
| statusClass: 'status-available', | |||
| avatarName: '战斗世界' | |||
| } | |||
| ] | |||
| } | |||
| }, | |||
| methods: { | |||
| goBack() { | |||
| uni.navigateBack() | |||
| }, | |||
| goTeam() { | |||
| uni.navigateTo({ | |||
| url: '/subPages/user/team' | |||
| }) | |||
| }, | |||
| goCash() { | |||
| uni.navigateTo({ | |||
| url: '/subPages/user/cash' | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .promote-page { | |||
| min-height: 100vh; | |||
| background: linear-gradient(124deg, #22F2EB 0%, #24B0F6 30%); | |||
| // background: linear-gradient(124deg, #22F2EB 0%, #24B0F6 100%); | |||
| } | |||
| .content { | |||
| padding: 0rpx 40rpx 0; | |||
| .promote-image-container { | |||
| display: flex; | |||
| justify-content: center; | |||
| margin-bottom: 30rpx; | |||
| align-items: center; | |||
| .promote-image { | |||
| margin: 0 auto; | |||
| width: 168rpx; | |||
| } | |||
| } | |||
| .slogan-container { | |||
| display: flex; | |||
| justify-content: center; | |||
| margin-bottom: 80rpx; | |||
| .slogan-image { | |||
| width: 670rpx; | |||
| } | |||
| } | |||
| } | |||
| // 外部大容器 | |||
| .main-container { | |||
| width: 100%; | |||
| border-radius: 48rpx; | |||
| border: 2rpx solid #06DADC12; | |||
| box-sizing: border-box; | |||
| padding: 40rpx; | |||
| padding-bottom: 200rpx; | |||
| background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #F0FBFF 100%); | |||
| // 个人信息容器 | |||
| .profile-container { | |||
| background: #fff; | |||
| margin-bottom: 30rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| border-radius: 48rpx; | |||
| border-width: 2rpx; | |||
| justify-content: space-between; | |||
| background: linear-gradient(180deg, #DEFFFF 0%, #FBFEFF 22.65%, #F0FBFF 100%); | |||
| // background: red; | |||
| border: 2rpx solid #06DADC12; | |||
| // padding-top: 32rpx; | |||
| padding-right: 40rpx; | |||
| // padding-bottom: 32rpx; | |||
| padding-left: 40rpx; | |||
| height: 200rpx; | |||
| .profile-avatar { | |||
| width: 128rpx; | |||
| height: 128rpx; | |||
| border-radius: 50%; | |||
| margin-right: 24rpx; | |||
| } | |||
| .profile-info { | |||
| flex: 1; | |||
| .profile-name { | |||
| display: block; | |||
| font-size: 32rpx; | |||
| font-weight: 600; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .profile-id { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| } | |||
| } | |||
| .profile-stats { | |||
| display: flex; | |||
| .stat-item { | |||
| text-align: center; | |||
| margin-left: 60rpx; | |||
| .stat-number { | |||
| display: block; | |||
| font-size: 32rpx; | |||
| font-weight: bold; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .stat-label { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 功能按钮区域 | |||
| .function-buttons { | |||
| display: flex; | |||
| justify-content: space-around; | |||
| align-items: center; | |||
| margin-bottom: 48rpx; | |||
| .function-item { | |||
| display: flex; | |||
| // flex-direction: column; | |||
| align-items: center; | |||
| gap: 16rpx; | |||
| border-right: 1px solid #06DADC; | |||
| padding-right: 30rpx; | |||
| &:nth-child(3) { | |||
| border-right: none; | |||
| } | |||
| .function-icon { | |||
| width: 46rpx; | |||
| height: 46rpx; | |||
| // margin-bottom: 16rpx; | |||
| } | |||
| .function-text { | |||
| font-size: 24rpx; | |||
| color: #181818; | |||
| } | |||
| } | |||
| } | |||
| // 余额显示 | |||
| .balance-section { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| margin-bottom: 40rpx; | |||
| .balance-label { | |||
| font-size: 32rpx; | |||
| color: #191919; | |||
| font-weight: 500; | |||
| } | |||
| .balance-amount { | |||
| font-size: 32rpx; | |||
| font-weight: 500; | |||
| color: #191919; | |||
| flex: 1; | |||
| margin-left: 20rpx; | |||
| } | |||
| } | |||
| // 转账记录容器 | |||
| .record-container { | |||
| .record-list { | |||
| border: 1px solid #F0F0F0; | |||
| border-radius: 24rpx; | |||
| // background: red; | |||
| .record-item { | |||
| height: 116rpx; | |||
| background: #fff; | |||
| // border-radius: 16rpx; | |||
| padding: 16rpx 32rpx; | |||
| // margin-bottom: 20rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| border-bottom: 2rpx solid #F1F1F1 ; | |||
| // margin-right: 24rpx; | |||
| // box-sizing: border-box; | |||
| .record-avatar{ | |||
| display: flex; | |||
| align-items: center; | |||
| flex-direction: column; | |||
| gap: 12rpx; | |||
| .avatar-name { | |||
| font-size: 24rpx; | |||
| color: #999; | |||
| } | |||
| .avatar { | |||
| width: 50rpx; | |||
| height: 50rpx; | |||
| border-radius: 50%; | |||
| // margin-right: 24rpx; | |||
| } | |||
| } | |||
| .record-info { | |||
| flex: 3; | |||
| text-align: center; | |||
| .record-title { | |||
| display: block; | |||
| font-size: 28rpx; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .record-date { | |||
| font-size: 26rpx; | |||
| color: #A3A3A3; | |||
| } | |||
| } | |||
| .record-amount { | |||
| flex: 2; | |||
| text-align: center; | |||
| .amount { | |||
| display: block; | |||
| font-size: 28rpx; | |||
| font-weight: bold; | |||
| color: #333; | |||
| margin-bottom: 8rpx; | |||
| } | |||
| .status { | |||
| font-size: 26rpx; | |||
| // padding: 8rpx 16rpx; | |||
| border-radius: 20rpx; | |||
| &.status-received { | |||
| // background: #f0f0f0; | |||
| color: #A3A3A3; | |||
| } | |||
| &.status-available { | |||
| // background: #22F2EB; | |||
| padding: 3rpx 16rpx; | |||
| color: $primary-color; | |||
| border: 2rpx solid $primary-color; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // 底部固定按钮 | |||
| .bottom-button-container { | |||
| position: fixed; | |||
| bottom: 0; | |||
| left: 0; | |||
| right: 0; | |||
| padding: 30rpx 40rpx; | |||
| background: rgba(255, 255, 255, 0.95); | |||
| border-top: 1px solid #F1F1F1; | |||
| // height: 143rpx; | |||
| // backdrop-filter: blur(10rpx); | |||
| } | |||
| </style> | |||
| @ -0,0 +1,199 @@ | |||
| <template> | |||
| <view class="team-page"> | |||
| <!-- 固定顶部搜索框 --> | |||
| <view class="fixed-header"> | |||
| <view class="search-container"> | |||
| <uv-search | |||
| v-model="searchKeyword" | |||
| placeholder="请输入" | |||
| :show-action="true" | |||
| action-text="搜索" | |||
| :animation="true" | |||
| bg-color="#f5f5f5" | |||
| @search="handleSearch" | |||
| @custom="handleSearch" | |||
| :action-style="{color: '#fff', backgroundColor: '#06DADC', borderRadius:'8rpx', width:'100rpx', height: '64rpx', lineHeight: '64rpx', borderRadius: '198rpx', text:'white', fontSize:'26rpx'}" | |||
| action | |||
| ></uv-search> | |||
| </view> | |||
| </view> | |||
| <!-- 内容区域 --> | |||
| <view class="content-area"> | |||
| <!-- 成员列表 --> | |||
| <view class="member-list"> | |||
| <view | |||
| class="member-item" | |||
| v-for="(member, index) in filteredMembers" | |||
| :key="index" | |||
| @click="handleMemberClick(member)" | |||
| > | |||
| <image | |||
| class="member-avatar" | |||
| :src="member.avatar || '/static/默认头像.png'" | |||
| mode="aspectFill" | |||
| ></image> | |||
| <text class="member-name">{{ member.name }}</text> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| export default { | |||
| data() { | |||
| return { | |||
| searchKeyword: '', | |||
| members: [ | |||
| { | |||
| id: 1, | |||
| name: '李世海', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 2, | |||
| name: '周静', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 3, | |||
| name: '周海', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 4, | |||
| name: '冯启彬', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 5, | |||
| name: '李嫣', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 6, | |||
| name: '李书萍', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 7, | |||
| name: '赵吾光', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 8, | |||
| name: '冯云', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 9, | |||
| name: '周静', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 10, | |||
| name: '周海', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 11, | |||
| name: '冯启彬', | |||
| avatar: '/static/默认头像.png' | |||
| }, | |||
| { | |||
| id: 12, | |||
| name: '李嫣', | |||
| avatar: '/static/默认头像.png' | |||
| } | |||
| ] | |||
| } | |||
| }, | |||
| computed: { | |||
| filteredMembers() { | |||
| if (!this.searchKeyword) { | |||
| return this.members | |||
| } | |||
| return this.members.filter(member => | |||
| member.name.includes(this.searchKeyword) | |||
| ) | |||
| } | |||
| }, | |||
| methods: { | |||
| handleSearch() { | |||
| // 搜索逻辑已通过computed实现 | |||
| console.log('搜索关键词:', this.searchKeyword) | |||
| }, | |||
| handleMemberClick(member) { | |||
| console.log('点击成员:', member) | |||
| // 可以在这里添加跳转到成员详情页的逻辑 | |||
| } | |||
| } | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| // @import '@/uni.scss'; | |||
| .team-page { | |||
| min-height: 100vh; | |||
| background-color: #f2f2f2; | |||
| // 固定顶部搜索框 | |||
| .fixed-header { | |||
| position: fixed; | |||
| top: 0; | |||
| left: 0; | |||
| right: 0; | |||
| z-index: 999; | |||
| background-color: #fff; | |||
| .search-container { | |||
| padding: 20rpx 30rpx; | |||
| background-color: #fff; | |||
| } | |||
| } | |||
| // 内容区域 | |||
| .content-area { | |||
| padding-top: 140rpx; // 为固定头部留出空间 | |||
| .member-list { | |||
| background-color: #fff; | |||
| margin: 0 40rpx; | |||
| border-radius: 32rpx; | |||
| .member-item { | |||
| display: flex; | |||
| align-items: center; | |||
| padding: 16rpx 32rpx; | |||
| height: 104rpx; | |||
| border-bottom: 2rpx solid #F1F1F1; | |||
| transition: background-color 0.3s; | |||
| &:active { | |||
| background-color: #f5f5f5; | |||
| } | |||
| &:last-child { | |||
| border-bottom: none; | |||
| } | |||
| .member-avatar { | |||
| width: 72rpx; | |||
| height: 72rpx; | |||
| border-radius: 50%; | |||
| margin-right: 24rpx; | |||
| background-color: #f0f0f0; | |||
| } | |||
| .member-name { | |||
| font-size: 32rpx; | |||
| color: #333; | |||
| font-weight: 400; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| </style> | |||