Intelligent-Medical-Guidance-Large-Model
/
frontend
/src
/views
/streaming
/StreamingRoomeEditView.vue
| <script setup lang="ts"> | |
| import { useRouter } from 'vue-router' | |
| import { onMounted, ref } from 'vue' | |
| import { ElMessage } from 'element-plus' | |
| import { Check, Warning, Edit } from '@element-plus/icons-vue' | |
| import { | |
| roomDetailRequest, | |
| roomPorductAddListRequest, | |
| RoomCreadeOrEditRequest, | |
| type RoomProductData, | |
| type RoomDetailItem, | |
| type StreamingRoomStatusItem, | |
| type StreamingRoomProductList, | |
| onAirRoomStartRequest | |
| } from '@/api/streamingRoom' | |
| import type { StreamerInfo } from '@/api/streamerInfo' | |
| import InfoDialogComponents from '@/components/InfoDialogComponents.vue' | |
| import { streamerInfoListRequest } from '@/api/streamerInfo' | |
| import StreamerInfoComponent from '@/components/StreamerInfoComponent.vue' | |
| import { AxiosError } from 'axios' | |
| const router = useRouter() | |
| // 定义 URL ID 传参 | |
| const props = defineProps({ | |
| roomId: { | |
| type: String, | |
| default: '0' | |
| } | |
| }) | |
| // 信息弹窗显示标识 | |
| const ShowItemInfo = ref() | |
| // 侧边栏 | |
| const DrawerProductList = ref({} as RoomProductData) | |
| DrawerProductList.value.product_list = [] // 设置默认值 | |
| DrawerProductList.value.totalSize = 0 | |
| const currentPage = ref(1) | |
| const pageSize = ref(-1) | |
| const getProductInfo = async () => { | |
| try { | |
| // 调用接口获取商品缩略图用于抽屉 | |
| const { data } = await roomPorductAddListRequest( | |
| RoomDetailInfo.value.room_id, | |
| currentPage.value, | |
| pageSize.value | |
| ) | |
| if (data.code === 0) { | |
| DrawerProductList.value = data.data | |
| // 分页获取 | |
| // if (DrawerProductList.value.product.length === 0) { | |
| // DrawerProductList.value = data.data | |
| // } else { | |
| // for (let i of data.data.product) { | |
| // // 根据返回数据继续添加商品 | |
| // DrawerProductList.value.product.push(i) | |
| // } | |
| // DrawerProductList.value.currentPage = data.data.currentPage | |
| // DrawerProductList.value.pageSize = data.data.pageSize | |
| // DrawerProductList.value.totalSize = data.data.totalSize | |
| // } | |
| console.info(DrawerProductList.value) | |
| ElMessage.success('获取商品成功') | |
| } else { | |
| ElMessage.error('获取商品失败:' + data.message) | |
| } | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('获取商品失败:' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| } | |
| // 获取商品表格信息 | |
| const RoomDetailInfo = ref({} as RoomDetailItem) | |
| RoomDetailInfo.value.streamer_info = {} as StreamerInfo | |
| RoomDetailInfo.value.streamer_info.streamer_id = 0 | |
| RoomDetailInfo.value.pageSize = 10 | |
| RoomDetailInfo.value.room_id = Number(props.roomId) | |
| RoomDetailInfo.value.product_list = [] as StreamingRoomProductList[] | |
| RoomDetailInfo.value.status = {} as StreamingRoomStatusItem | |
| const EditProductList = ref({} as RoomDetailItem) | |
| const getProductListInfo = async (currentPage: number, pageSize: number) => { | |
| if (RoomDetailInfo.value.room_id === 0) { | |
| return | |
| } | |
| try { | |
| const { data } = await roomDetailRequest( | |
| String(RoomDetailInfo.value.room_id), | |
| currentPage, | |
| pageSize | |
| ) | |
| if (data.code === 0) { | |
| console.info(data.data) | |
| RoomDetailInfo.value = data.data | |
| } else { | |
| ElMessage.error('获取直播间详情失败' + data.message) | |
| } | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('获取直播间详情失败' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| } | |
| // 获取主播信息 | |
| const streamerNameOptions = ref([] as StreamerInfo[]) | |
| const getSteramerInfo = async () => { | |
| try { | |
| // 获取主播信息 | |
| const { data } = await streamerInfoListRequest() | |
| if (data.code === 0) { | |
| streamerNameOptions.value = data.data | |
| ElMessage.success('获取主播信息成功') | |
| } else { | |
| ElMessage.error('获取主播信息失败' + data.message) | |
| } | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('获取主播信息失败' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| } | |
| onMounted(() => { | |
| // 获取商品表格信息 | |
| getProductListInfo(1, 10) | |
| // 获取主播信息 | |
| getSteramerInfo() | |
| }) | |
| // 新增商品 | |
| const handelAddProductClick = async () => { | |
| // 先保存商品,防止文案 or 数字人视频丢失 | |
| // onSubmit() | |
| drawerShow.value = true | |
| getProductInfo() | |
| } | |
| const drawerShow = ref(false) | |
| function cancelClick() { | |
| drawerShow.value = false | |
| } | |
| async function confirmClick() { | |
| EditProductList.value = RoomDetailInfo.value | |
| EditProductList.value.product_list = DrawerProductList.value.product_list | |
| EditProductList.value.streamer_id = RoomDetailInfo.value.streamer_info.streamer_id | |
| console.log(EditProductList.value) | |
| try { | |
| // 调用接口更新选择的商品 | |
| const { data } = await RoomCreadeOrEditRequest(EditProductList.value) | |
| if (data.code === 0) { | |
| // 新建会返回直播间后台保存 ID | |
| RoomDetailInfo.value.room_id = data.data | |
| ElMessage.success('操作成功') | |
| } else { | |
| ElMessage.error('操作失败' + data.message) | |
| } | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('操作失败' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| drawerShow.value = false | |
| // 重新获取 | |
| getProductListInfo(1, 10) | |
| } | |
| // 保存 | |
| const onSubmit = async () => { | |
| try { | |
| // 调用接口保存商品 | |
| await RoomCreadeOrEditRequest(RoomDetailInfo.value) | |
| ElMessage.success('保存成功') | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('保存失败' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| } | |
| const handelOnAirClick = async () => { | |
| for (const entry of RoomDetailInfo.value.product_list) { | |
| if (entry.start_video === '') { | |
| ElMessage.error('必须将所有的商品都生成数字人视频才可以进行开播') | |
| return false | |
| } | |
| } | |
| // 保存商品信息 | |
| await onSubmit() | |
| if (RoomDetailInfo.value.status.live_status !== 1) { | |
| try { | |
| // 调用接口执行开播 | |
| await onAirRoomStartRequest(RoomDetailInfo.value.room_id) | |
| ElMessage.success('开播成功') | |
| } catch (error: unknown) { | |
| if (error instanceof AxiosError) { | |
| ElMessage.error('开播成功' + error.message) | |
| } else { | |
| ElMessage.error('未知错误:' + error) | |
| } | |
| } | |
| } | |
| router.push({ name: 'StreamingOnAir', params: { roomId: String(RoomDetailInfo.value.room_id) } }) | |
| } | |
| // 每个物品的点击按钮 | |
| const handelControlClick = ( | |
| titleName: string, | |
| itemType: string, | |
| itemValue: string, | |
| productId: number, | |
| streamerId: number, | |
| salesDoc: string | |
| ) => { | |
| console.info(itemType) | |
| console.info(itemValue) | |
| ShowItemInfo.value.showItemInfoDialog( | |
| titleName, | |
| itemType, | |
| itemValue, | |
| productId, | |
| streamerId, | |
| salesDoc | |
| ) | |
| } | |
| </script> | |
| <template> | |
| <div> | |
| <!-- 返回栏 --> | |
| <el-page-header @back="router.push({ name: 'StreamingOverview' })" title="返回"> | |
| <template #content> | |
| <div class="flex items-center"> | |
| <span class="text-large font-600 mr-3"> | |
| {{ RoomDetailInfo.room_id !== 0 ? '编辑' : '新建' }} 直播间 | |
| </span> | |
| </div> | |
| </template> | |
| </el-page-header> | |
| <!-- 新增窗口右边抽屉弹窗 --> | |
| <el-drawer v-model="drawerShow" direction="rtl"> | |
| <template #header> | |
| <h1>添加商品</h1> | |
| </template> | |
| <template #default> | |
| <div> | |
| <ul class="product-list"> | |
| <li | |
| v-for="item in DrawerProductList.product_list" | |
| :key="item.product_id" | |
| style="margin-bottom: 10px" | |
| > | |
| <el-checkbox-button | |
| v-model="item.selected" | |
| size="large" | |
| border | |
| class="item-checkbox-button" | |
| > | |
| <el-card shadow="never"> | |
| <el-row :gutter="0"> | |
| <el-col :span="6"> | |
| <el-image | |
| style="width: 80px; height: 80px" | |
| :src="item.product_info.image_path" | |
| fit="contain" | |
| /> | |
| </el-col> | |
| <el-col :span="18"> | |
| <div class="product-info"> | |
| <p class="title">{{ item.product_info.product_name }}</p> | |
| <p class="content">{{ item.product_info.heighlights }}</p> | |
| <p class="price">¥{{ item.product_info.selling_price }}</p> | |
| </div> | |
| </el-col> | |
| </el-row> | |
| </el-card> | |
| </el-checkbox-button> | |
| </li> | |
| </ul> | |
| </div> | |
| </template> | |
| <template #footer> | |
| <div style="flex: auto"> | |
| <el-button @click="cancelClick">取消</el-button> | |
| <el-button type="primary" @click="confirmClick">确认</el-button> | |
| </div> | |
| </template> | |
| </el-drawer> | |
| <el-card shadow="never" style="margin-top: 10px"> | |
| <h2>直播间名称</h2> | |
| <el-divider /> | |
| <el-input v-model="RoomDetailInfo.name" size="large" /> | |
| </el-card> | |
| <el-card shadow="never"> | |
| <StreamerInfoComponent | |
| :disable-change="true" | |
| v-model="RoomDetailInfo.streamer_info" | |
| :optionList="streamerNameOptions" | |
| /> | |
| </el-card> | |
| <el-card shadow="never"> | |
| <el-button | |
| type="primary" | |
| style="margin-bottom: 15px" | |
| @click="handelAddProductClick" | |
| size="large" | |
| round | |
| > | |
| <el-icon style="margin-right: 5px"> | |
| <Edit /> | |
| </el-icon> | |
| 增删商品 | |
| </el-button> | |
| <!-- TODO 商品表格可以做成 component 组件 --> | |
| <el-table :data="RoomDetailInfo.product_list" max-height="1000" border> | |
| <el-table-column prop="product_info.product_id" label="ID" align="center" width="50px" /> | |
| <el-table-column prop="product_info.image_path" label="图片" align="center"> | |
| <template #default="scope"> | |
| <div style="display: flex; align-items: center"> | |
| <!-- TODO 加上 :preview-src-list="[scope.row.image_path]" --> | |
| <el-image :src="scope.row.product_info.image_path" /> | |
| </div> | |
| </template> | |
| </el-table-column> | |
| <el-table-column prop="product_info.product_name" label="名称" align="center" /> | |
| <el-table-column prop="product_info.product_class" label="分类" align="center" /> | |
| <el-table-column prop="product_info.heighlights" label="亮点" align="center" /> | |
| <el-table-column prop="product_info.selling_price" label="价格" align="center" /> | |
| <el-table-column prop="product_info.amount" label="库存" align="center" /> | |
| <el-table-column prop="product_info.departure_place" label="发货地" align="center" /> | |
| <el-table-column prop="product_info.delivery_company" label="快递公司" align="center" /> | |
| <el-table-column prop="product_info.upload_date" label="上传时间" align="center" /> | |
| <el-table-column label="操作" v-slot="{ row }" align="center" width="400px"> | |
| <div class="control-item"> | |
| <el-button | |
| size="small" | |
| :type="row.product_info.instruction !== '' ? 'success' : 'warning'" | |
| :icon="row.product_info.instruction !== '' ? Check : Warning" | |
| @click=" | |
| handelControlClick( | |
| row.product_info.product_name, | |
| 'Instruction', | |
| row.product_info.instruction, | |
| row.product_id, | |
| RoomDetailInfo.streamer_info.streamer_id, | |
| row.sales_doc | |
| ) | |
| " | |
| > | |
| 说明书 | |
| </el-button> | |
| <el-button | |
| size="small" | |
| v-model="row.sales_doc" | |
| :type="row.sales_doc !== '' ? 'success' : 'warning'" | |
| :icon="row.sales_doc !== '' ? Check : Warning" | |
| @click=" | |
| handelControlClick( | |
| row.product_info.product_name, | |
| 'SalesDoc', | |
| row.sales_doc, | |
| row.product_id, | |
| RoomDetailInfo.streamer_info.streamer_id, | |
| row.sales_doc | |
| ) | |
| " | |
| > | |
| 解说文案 | |
| </el-button> | |
| <el-button | |
| size="small" | |
| v-model="row.start_video" | |
| :type="row.start_video !== '' ? 'success' : 'warning'" | |
| :icon="row.start_video !== '' ? Check : Warning" | |
| @click=" | |
| handelControlClick( | |
| row.product_info.product_name, | |
| 'DigitalHuman', | |
| row.start_video, | |
| row.product_id, | |
| RoomDetailInfo.streamer_info.streamer_id, | |
| row.sales_doc | |
| ) | |
| " | |
| > | |
| 数字人视频 | |
| </el-button> | |
| <el-button | |
| size="small" | |
| @click="router.push({ name: 'ProductEdit', params: { productId: row.product_id } })" | |
| > | |
| 编辑 | |
| </el-button> | |
| </div> | |
| </el-table-column> | |
| </el-table> | |
| <!-- 信息弹窗 --> | |
| <InfoDialogComponents ref="ShowItemInfo" v-model="RoomDetailInfo.product_list" /> | |
| <template #footer> | |
| <div class="bottom-item"> | |
| <el-pagination | |
| v-model:current-page="RoomDetailInfo.currentPage" | |
| v-model:page-size="RoomDetailInfo.pageSize" | |
| :page-sizes="[5, 10, 15, 20]" | |
| :background="true" | |
| layout="total, sizes, prev, pager, next, jumper" | |
| :total="RoomDetailInfo.totalSize || 0" | |
| @size-change="(pageSize: number) => getProductListInfo(1, pageSize)" | |
| @current-change=" | |
| (currentPage: number) => getProductListInfo(currentPage, RoomDetailInfo.pageSize) | |
| " | |
| /> | |
| <div> | |
| <el-button | |
| type="success" | |
| @click="handelOnAirClick" | |
| :disable="RoomDetailInfo.room_id === 0" | |
| > | |
| {{ RoomDetailInfo.status.live_status === 1 ? '进入' : '开始' }}直播</el-button | |
| > | |
| <el-button | |
| type="primary" | |
| @click="onSubmit" | |
| :disabled="RoomDetailInfo.product_list.length === 0" | |
| >保存</el-button | |
| > | |
| </div> | |
| </div> | |
| </template> | |
| </el-card> | |
| </div> | |
| </template> | |
| <style lang="scss" scoped> | |
| .bottom-item { | |
| margin-top: 10px; // 距离上面的控件有一定的距离 | |
| display: flex; | |
| justify-content: space-between; // 将两个 div 放置在页面的两侧 | |
| align-items: center; | |
| } | |
| .product-list { | |
| padding-left: 0; /* 去掉默认的缩进 */ | |
| margin: 0; /* 去掉默认的外边距 */ | |
| list-style-type: none; /* 去掉列表项前的默认圆点 */ | |
| .ul { | |
| list-style-type: none; | |
| padding-left: 0; /* 去掉默认的缩进 */ | |
| } | |
| } | |
| .el-card { | |
| margin-bottom: 20px; | |
| padding: 20px; | |
| border-radius: 20px; | |
| } | |
| ::v-deep(.el-input__wrapper) { | |
| border-radius: 14px; | |
| } | |
| .item-checkbox-button { | |
| ::v-deep(.el-checkbox-button__inner) { | |
| border-radius: 20px; /* 设置 checkbox button 圆角大小 */ | |
| line-height: 0; | |
| text-align: left; | |
| padding: 5px 5px; | |
| } | |
| .el-card__body { | |
| padding: 0px !important; | |
| } | |
| .el-card { | |
| margin: 0px; | |
| width: 450px; | |
| height: 120px; | |
| padding: 0px; | |
| .product-info { | |
| display: flex; | |
| flex-direction: column; /* 将子元素垂直排列 */ | |
| margin-left: 10px; | |
| .title { | |
| font-size: 14px; | |
| font-weight: 600; | |
| } | |
| .content { | |
| font-size: 12px; | |
| color: #b1b3b8; | |
| } | |
| .price { | |
| font-size: 12px; | |
| color: #fda100; | |
| } | |
| } | |
| } | |
| } | |
| </style> | |