| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- <template>
- <view class="page-one-container">
- <!-- 图片资料标题 -->
- <view class="page-header">
-
- <view class="detail-image-header">
- <text class="detail-image-title">图片资料</text>
- <view class="copy-btn" @click="handleSaveAllImages">
- <text>一键复制</text>
- </view>
- </view>
- </view>
- <!-- 聊天记录/通话记录/跟进卡片 -->
- <view class="card-wrap">
- <view class="card-title">
- <text :class="{ 'active': recordType === 'chat' }" @click="recordType = 'chat'">
- 聊天记录
- </text>
- <text class="divider">|</text>
- <text :class="{ 'active': recordType === 'call' }" @click="recordType = 'call'">
- 通话记录
- </text>
- <text class="divider">|</text>
- <text :class="{ 'active': recordType === 'frontendFollow' }" @click="recordType = 'frontendFollow'">
- 前端跟进
- </text>
- <text class="divider">|</text>
- <text :class="{ 'active': recordType === 'followRecord' }" @click="recordType = 'followRecord'">
- 跟进记录
- </text>
- </view>
- <!-- 聊天记录 -->
- <view v-if="recordType === 'chat'" class="image-upload-container">
- <view class="image-list">
- <view v-for="(item, index) in chatRecordsList" :key="`chat-${index}`" class="image-item">
- <PicComp :src="item.fileUrl" @needPreviewPic="previewImage" />
- <view class="delete-btn" @click="handleDeleteImage(item)">×</view>
- </view>
- <view class="upload-btn" @click="handleUploadImage('chatRecords')">
- <u-icon name="plus" size="40" color="#999" />
- </view>
- </view>
- </view>
- <!-- 通话录音 -->
- <view v-if="recordType === 'call'" class="call-records-container">
- <sound-recorder v-for="item in soundRecordList" :key="item.fileName" :data="item"
- @handleDelectThisSoundRecord="handleDeleteSoundRecord" />
- </view>
- <!-- 前端跟进 -->
- <follow-card v-else-if="recordType === 'frontendFollow'" :clue-id="currentClueId" type="4" />
- <!-- 跟进记录 -->
- <follow-card v-else-if="recordType === 'followRecord'" :clue-id="currentClueId" type="5" />
- </view>
- <!-- 实物图卡片 -->
- <view class="card-wrap">
- <view class="card-title">实物图</view>
- <view class="image-upload-container">
- <view class="image-list">
- <view v-for="(item, index) in truePicList" :key="`truePic-${index}`" class="image-item">
- <PicComp :src="item.fileUrl" @needPreviewPic="previewTrueImage" />
- <view class="delete-btn" @click="handleDeleteImage(item)">×</view>
- </view>
- <view class="upload-btn" @click="handleUploadImage('truePic')">
- <u-icon name="plus" size="40" color="#999" />
- </view>
- </view>
- </view>
- </view>
- <!-- 基本信息卡片 -->
- <view class="info-card">
- <view class="info-card-title">基本信息</view>
- <u-row class="info-row">
- <u-col span="6">
- <view class="info-label">发单人</view>
- <view class="info-value">{{ orderDetail.createNickName || '未填写' }}</view>
- </u-col>
- <u-col span="6">
- <view class="info-label">型号</view>
- <view class="info-value">{{ orderDetail.model || '未填写' }}</view>
- </u-col>
- </u-row>
- <u-row class="info-row">
- <u-col span="6">
- <view class="info-label">上门时间</view>
- <view class="info-value">{{ orderDetail.visitTime || '未填写' }}</view>
- </u-col>
- <u-col span="6">
- <view class="info-label">地址</view>
- <view class="info-value">{{ orderDetail.address || '未填写' }}</view>
- </u-col>
- </u-row>
- </view>
- <!-- 联系方式卡片 -->
- <view class="contact-card">
- <view class="contact-item phone-card" @click="handlePhoneClick">
- <u-icon name="phone" size="40" color="#07C160" />
- <view class="contact-title">电话</view>
- <view v-if="orderDetail.phone" class="red-dot"></view>
- </view>
- <view class="contact-item wechat-card" @click="handleWechatClick">
- <u-icon name="chat" size="40" color="#07C160" />
- <view class="contact-title">微信</view>
- <view v-if="orderDetail.wechat" class="red-dot"></view>
- </view>
- </view>
- <!-- 下一步按钮 -->
- <view class="space-block"></view>
- <u-button class="next-btn" @click="handleNext" type="primary" size="middle">
- 下一步
- </u-button>
- </view>
- </template>
- <script>
- import PicComp from './PicComp.vue'
- import soundRecorder from '@/components/soundRecorder/soundRecorder.vue'
- import FollowCard from './FollowCard.vue'
- import imageUpload from '../utils/imageUpload.js'
- export default {
- name: 'PageOne',
- components: {
- PicComp,
- soundRecorder,
- FollowCard
- },
- props: {
- orderDetail: {
- type: Object,
- default: () => ({})
- },
- orderId: {
- type: String,
- default: ''
- },
- currentReceipt: {
- type: Object,
- default: () => ({})
- }
- },
- data() {
- return {
- recordType: 'chat', // 'chat' | 'call' | 'frontendFollow' | 'followRecord'
- chatRecordsList: [],
- truePicList: [],
- soundRecordList: []
- }
- },
- computed: {
- currentClueId() {
- return (this.currentReceipt && this.currentReceipt.clueId) || (this.orderDetail && this.orderDetail.clueId) || ''
- }
- },
- watch: {
- currentReceipt: {
- handler(newVal) {
- if (newVal && newVal.id) {
- this.loadImageList()
- this.loadCallRecords()
- }
- },
- immediate: true,
- deep: true
- }
- },
- methods: {
- /**
- * 加载图片列表
- */
- async loadImageList() {
- if (!this.currentReceipt.id || !this.orderDetail.itemBrand) return
- try {
- // 加载聊天记录
- const chatList = await imageUpload.getFileList(
- '2',
- '1',
- this.currentReceipt.id,
- this.orderDetail.itemBrand,
- this.currentReceipt.clueId
- )
- this.chatRecordsList = chatList || []
- // 加载实物图
- const truePicList = await imageUpload.getFileList(
- '2',
- '2',
- this.currentReceipt.id,
- this.orderDetail.itemBrand,
- this.currentReceipt.clueId
- )
- this.truePicList = truePicList || []
- } catch (error) {
- console.error('加载图片列表失败:', error)
- }
- },
- /**
- * 加载通话记录
- */
- async loadCallRecords() {
- if (!this.currentReceipt.clueId) return
- try {
- const { data } = await uni.$u.api.getCallClueFileByClueId({
- clueId: this.currentReceipt.clueId
- })
- this.soundRecordList = data || []
- } catch (error) {
- console.error('加载通话记录失败:', error)
- }
- },
- /**
- * 上传图片
- */
- async handleUploadImage(type) {
- try {
- const filePaths = await imageUpload.chooseImage(9)
- const uploadResults = await imageUpload.uploadFiles(filePaths)
- // 绑定订单文件
- const orderFileType = type === 'truePic' ? '2' : '1'
- await imageUpload.bindOrderFile(
- this.currentReceipt.clueId,
- this.currentReceipt.id,
- orderFileType,
- uploadResults
- )
- // 刷新列表
- this.loadImageList()
- } catch (error) {
- console.error('上传图片失败:', error)
- }
- },
- /**
- * 删除图片
- */
- async handleDeleteImage(item) {
- uni.showModal({
- title: '提示',
- content: '确定要删除这张图片吗?',
- success: async (res) => {
- if (res.confirm) {
- try {
- await imageUpload.deleteFile(item.id)
- this.loadImageList()
- } catch (error) {
- console.error('删除图片失败:', error)
- }
- }
- }
- })
- },
- /**
- * 删除录音
- */
- async handleDeleteSoundRecord({ id }) {
- uni.showModal({
- title: '提示',
- content: '是否确定删除?',
- success: async (res) => {
- if (res.confirm) {
- try {
- await uni.$u.api.deleteClueFile([id])
- uni.showToast({
- title: '删除成功',
- icon: 'success'
- })
- this.loadCallRecords()
- } catch (error) {
- uni.showToast({
- title: '删除失败',
- icon: 'error'
- })
- }
- }
- }
- })
- },
- /**
- * 预览图片
- */
- previewImage(src) {
- const urlList = this.chatRecordsList.map(item => item.fileUrl)
- uni.previewImage({
- urls: urlList,
- current: src
- })
- },
- /**
- * 预览实物图
- */
- previewTrueImage(src) {
- const urlList = this.truePicList.map(item => item.fileUrl)
- uni.previewImage({
- urls: urlList,
- current: src
- })
- },
- /**
- * 保存全部图片
- */
- async handleSaveAllImages() {
- const allUrls = this.truePicList.map(item => item.fileUrl)
- if (allUrls.length === 0) {
- uni.showToast({
- title: '没有图片可保存',
- icon: 'none'
- })
- return
- }
- uni.showModal({
- title: '保存图片',
- content: `是否将 ${allUrls.length} 张图片保存到本地相册?`,
- confirmText: '保存',
- success: (res) => {
- if (res.confirm) {
- imageUpload.saveImagesToLocal(allUrls)
- }
- }
- })
- },
- /**
- * 电话点击
- */
- handlePhoneClick() {
- if (!this.orderDetail.phone) {
- uni.showToast({
- title: '该订单暂时没有电话号码',
- icon: 'none'
- })
- return
- }
- uni.makePhoneCall({
- phoneNumber: this.orderDetail.phone,
- success: () => {
- this.$store.commit('call/SET_FORM', {
- clueId: this.orderDetail.clueId,
- type: '3',
- callee: this.orderDetail.phone
- })
- }
- })
- },
- /**
- * 微信点击
- */
- handleWechatClick() {
- if (!this.orderDetail.wechat) {
- uni.showToast({
- title: '该订单暂时没有微信号',
- icon: 'none'
- })
- return
- }
- uni.setClipboardData({
- data: this.orderDetail.wechat,
- success: () => {
- uni.showToast({
- title: '微信号已复制',
- icon: 'none'
- })
- }
- })
- },
- /**
- * 下一步
- */
- handleNext() {
- this.$emit('next', {
- nowPage: 'formOne',
- form: {}
- })
- }
- }
- }
- </script>
- <style scoped lang="scss">
- @import '../styles/common.scss';
- .page-one-container {
- @extend .page-container;
- padding-bottom: 100rpx;
- }
- .page-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20rpx;
- }
- .page-title {
- @include font-styles($size: title, $weight: bold, $color: primary);
- }
- .save-all-btn {
- border-radius: 20rpx;
- border-color: #007AFF;
- color: #007AFF;
- }
- .card-wrap {
- @extend .card-wrap;
- margin-top: 20rpx;
- }
- .card-title {
- padding: 20rpx 15rpx;
- border-bottom: 1rpx solid map-get($colors, border);
- display: flex;
- align-items: center;
- white-space: nowrap;
- overflow-x: auto;
- -webkit-overflow-scrolling: touch;
- text {
- padding: 0 6rpx;
- cursor: pointer;
- font-size: 26rpx;
- white-space: nowrap;
- flex-shrink: 0;
- &.active {
- color: map-get($colors, primary);
- font-weight: bold;
- }
- }
- .divider {
- margin: 0 4rpx;
- color: #ddd;
- font-size: 24rpx;
- flex-shrink: 0;
- }
- }
- .image-upload-container {
- padding: 20rpx;
- }
- .image-list {
- display: flex;
- flex-wrap: wrap;
- gap: 20rpx;
- }
- .image-item {
- position: relative;
- width: 200rpx;
- height: 200rpx;
- box-sizing: border-box;
- }
- .delete-btn {
- position: absolute;
- top: -10rpx;
- right: -10rpx;
- width: 40rpx;
- height: 40rpx;
- background-color: #ff4d4f;
- color: #fff;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 30rpx;
- font-weight: bold;
- z-index: 10;
- cursor: pointer;
- }
- .upload-btn {
- width: 200rpx;
- height: 200rpx;
- border: 8rpx dashed #ddd;
- border-radius: 30rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: #f9f9f9;
- box-sizing: border-box;
- cursor: pointer;
- }
- .call-records-container {
- padding: 20rpx;
- }
- .info-card {
- @extend .card-wrap;
- padding: 20rpx;
- margin-top: 20rpx;
- box-sizing: border-box;
- width: 100%;
- max-width: 100%;
- }
- .info-card-title {
- @include font-styles($size: title, $weight: bold, $color: primary);
- margin-bottom: 25rpx;
- padding-bottom: 15rpx;
- border-bottom: 1rpx solid map-get($colors, border);
- }
- .info-row {
- margin-bottom: 20rpx;
- }
- .info-label {
- @include font-styles($size: tiny, $weight: regular, $color: tertiary);
- margin-bottom: 8rpx;
- }
- .info-value {
- @include font-styles($size: small, $weight: regular, $color: secondary);
- word-break: break-all;
- }
- .contact-card {
- display: flex;
- justify-content: space-between;
- margin: 20rpx 0;
- gap: 20rpx;
- }
- .contact-item {
- flex: 1;
- @extend .card-wrap;
- padding: 20rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- position: relative;
- cursor: pointer;
- }
- .contact-title {
- @include font-styles($size: tiny, $weight: regular, $color: tertiary);
- margin-top: 10rpx;
- }
- .red-dot {
- position: absolute;
- top: 15rpx;
- right: 15rpx;
- width: 25rpx;
- height: 25rpx;
- background-color: #ff4d4f;
- border-radius: 50%;
- box-shadow: 0 0 4rpx rgba(255, 77, 79, 0.3);
- }
- .space-block {
- height: 100rpx;
- }
- .next-btn {
- position: fixed;
- bottom: 10rpx;
- left: 2.5%;
- width: 95%;
- height: 80rpx;
- line-height: 80rpx;
- text-align: center;
- border-radius: 20rpx;
- }
- .detail-image-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 100%;
- border-bottom: 1rpx solid map-get($colors, border);
- }
- .detail-image-title {
- @include font-styles($size: content, $weight: bold, $color: primary);
- }
- .copy-btn {
- border-radius: 20rpx;
- border: 1rpx solid #007AFF;
- background-color: transparent;
- color: #007AFF;
- padding: 0 24rpx;
- height: 64rpx;
- line-height: 64rpx;
- cursor: pointer;
- }
- </style>
|