123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- <template>
- <div ref="headerRef" class="header">
- <div style="display: flex; flex-direction: row" class="header-title-tab">
- <h3>{{ t('room.myRoom') }}({{ roomStore.list.length }})</h3>
- <a-radio-group
- v-model:value="roomType"
- button-style="solid"
- class="select-group"
- >
- <a-radio-button :value="0">{{ t('base.all') }}</a-radio-button>
- <a-radio-button :value="1">{{ t('base.using') }}</a-radio-button>
- <a-radio-button :value="2">{{ t('base.end') }}</a-radio-button>
- </a-radio-group>
- <!-- <a-button type="text" @click="roomStore.setRoomStatus(2)">
- <h3>{{ t('room.myEndRoom') }} ({{ roomStore.endlist.length }})</h3>
- </a-button> -->
- </div>
- <a-input
- v-model:value="keyword"
- :placeholder="t('room.searchRoom')"
- class="room-search"
- allow-clear
- >
- <template #prefix><search-outlined class="room-search-icon" /></template>
- </a-input>
- </div>
- <DataList
- un-search-desc=" "
- :data-source="roomList.filter(room => room !== addMarked)"
- :keyword="keyword"
- name="作品"
- >
- <template v-if="!keyword" #undata>
- <a-button
- type="primary"
- shape="round"
- size="middle"
- @click="editRoom()"
- v-if="isRoomAll"
- >
- {{ t('room.createRoom') }}
- </a-button>
- <span v-else>{{ t('room.nodata') }}</span>
- </template>
- <a-list
- :grid="{ gutter: 20, xl: 5, lg: 4, md: 3, sm: 2, xs: 1, column: 5 }"
- :data-source="roomList"
- class="page-list"
- >
- <template #renderItem="{ item }">
- <a-list-item>
- <RoomSign
- v-if="item !== addMarked"
- :room="item"
- :disabled="item.roomStatus === 2"
- @web-sync="webSyncRoom(item)"
- @delete="deleteRoom(item)"
- @share="shareRoom(item)"
- @mini-sync="miniSyncRoom(item, 'leader')"
- @edit="editRoom(item)"
- />
- <template v-else>
- <a-card
- v-if="isRoomAll"
- class="add-room"
- hoverable
- @click="editRoom()"
- >
- <a-button shape="circle" class="button" type="primary">
- <plus-outlined class="add-room-icon" />
- </a-button>
- <p>{{ t('room.createRoom') }}</p>
- </a-card>
- </template>
- </a-list-item>
- </template>
- </a-list>
- </DataList>
- <teleport v-if="!headerVisible" to="#app">
- <div class="content-layout goto-layer">
- <div
- class="goto-top"
- @click="contentRef?.scroll({ left: 0, top: 0, behavior: 'smooth' })"
- >
- <vertical-align-top-outlined />
- </div>
- </div>
- </teleport>
- </template>
- <script setup lang="ts">
- import { useRoomStore } from '@/store/modules/room'
- import { useUserStore } from '@/store/modules/user'
- import { ref, computed, createVNode, unref, watch } from 'vue'
- import { message, Modal } from 'ant-design-vue'
- import { copyText } from '@/shared'
- import { renderModal } from '@/helper'
- import { userApp } from '@/main'
- import { useVisible } from '@/hook'
- import { contentRef } from '@/App.vue'
- import EditRoom from './edit-room'
- import RoomSign from './sign.vue'
- import Share from './modal/share.vue'
- import MiniSync from './modal/mini-sync.vue'
- import DataList from '@/components/data-list/index.vue'
- import { useI18n } from '@/hook/useI18n'
- import type { Room } from '@/store/modules/room'
- import { fetchRoomDetail, checkRoomEditOrDel } from '@/api'
- import { useLocale } from '@/locales/useLocale'
- defineOptions({ name: 'RoomList' })
- const isMiniApp = ref(import.meta.env.VITE_IS_MINIAPP)
- const addMarked = Symbol('add-room')
- const roomStore = useRoomStore()
- const { t } = useI18n()
- const keyword = ref('')
- const roomType = ref(roomStore.roomStatus)
- watch(
- () => roomType,
- val => {
- console.log('roomType', unref(val))
- switch (unref(val)) {
- case 0:
- roomStore.setRoomStatus(0)
- break
- case 1:
- roomStore.setRoomStatus(1)
- break
- case 2:
- roomStore.setRoomStatus(2)
- break
- default:
- roomStore.setRoomStatus(0)
- break
- }
- },
- {
- deep: true,
- immediate: true
- }
- )
- const roomList = computed(() =>
- roomStore.roomStatus === 0
- ? [addMarked, ...roomStore.filter(keyword.value)]
- : roomStore.filter(keyword.value)
- )
- const isRoomAll = computed(() => roomStore.roomStatus === 0)
- const deleteRoom = async (room: Room) => {
- // xxx
- const res = await checkRoomEditOrDel(room)
- if (!res) {
- message.error(t('room.roomOnfired'))
- return
- }
- Modal.confirm({
- content: t('room.deletedScenesWaring'),
- title: t('room.deletedRoom'),
- width: '400px',
- okText: t('base.delete'),
- icon: null,
- cancelText: t('base.cancel'),
- onOk: () => roomStore.delete(room)
- })
- }
- const shareRoom = async (room: Room) => {
- if (Number(unref(isMiniApp)) === 1) {
- await roomStore.setRoomMiniCode(room)
- miniSyncRoom(room)
- } else {
- const scenes = await fetchRoomDetail(room.id)
- const { app } = userApp()
- const m = scenes.sceneData[0].num
- Modal.confirm({
- content: createVNode(Share, { room, num: m }),
- title: t('base.share'),
- icon: null,
- width: '500px',
- okText: t('room.copyLink'),
- appContext: app._context,
- cancelText: t('base.cancel'),
- onOk: async () => {
- const { getLocale } = useLocale()
- const link = roomStore.getShareUrl({
- roomId: room.id,
- num: m,
- role: 'customer',
- isTour: '1',
- lang: unref(getLocale) || 'zh'
- })
- await copyText(link)
- message.success(t('room.linkCopySuccess'))
- }
- })
- }
- }
- const miniSyncRoom = async (room: Room, key?: 'leader') => {
- let miniCode: string
- let descs: string[]
- let title: string
- if (key === 'leader') {
- await roomStore.setLeaderRoomMiniCode(room)
- miniCode = room.leaderMiniCode!
- descs = [t('room.openScanMiniApp'), t('room.enterWechat')]
- title = t('room.startMiniAppLivestreaming')
- } else {
- await roomStore.setRoomMiniCode(room)
- miniCode = room.miniCode!
- descs = [t('room.shareFriends'), t('room.scanMiniApp')]
- title = t('base.share')
- }
- renderModal(MiniSync, {
- title,
- miniCode,
- descs
- })
- }
- const webSyncRoom = async (room: Room) => {
- // debugger
- const scenes = await fetchRoomDetail(room.id)
- const { getLocale } = useLocale()
- const user = useUserStore().current
- console.log('scenes', scenes)
- const m = scenes.sceneData[0].num
- const link = roomStore.getShareUrl({
- roomId: room.id,
- num: m,
- role: 'leader',
- name: encodeURIComponent(scenes.roomHostName),
- avatar: encodeURIComponent(user.avatar) || '',
- userId: '1',
- isTour: '0',
- lang: unref(getLocale) || 'zh'
- })
- console.log('带看link', link)
- window.open(link, '_blank')
- }
- const editRoom = async (room?: Room) => {
- if (room) {
- // if (!res) {
- // message.error(t('room.roomOnfired'))
- // return
- // }
- const scenes = await roomStore.setRoomScenes(room)
- room = Object.assign({}, room, scenes)
- }
- // debugger
- renderModal(EditRoom, {
- room,
- async onSave(actionRoom) {
- if (room) {
- const res = await checkRoomEditOrDel(room)
- if (res) {
- await roomStore.update(actionRoom)
- }
- } else {
- await roomStore.insert(actionRoom)
- }
- message.success(t('base.saveSuccess'))
- }
- })
- }
- const headerRef = ref<HTMLElement>()
- const headerVisible = useVisible({
- target: headerRef,
- parent: contentRef,
- bound: -140
- })
- </script>
- <style scoped lang="scss">
- .header {
- padding: 0 30px;
- height: 80px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- background-color: #fff;
- margin: 30px 0;
- .room-search {
- width: 290px;
- height: 40px;
- border-radius: 20px;
- }
- .room-search-icon {
- color: #cfd0d3;
- }
- }
- .add-room {
- height: 321px;
- cursor: pointer;
- display: flex;
- text-align: center;
- align-items: center;
- justify-content: center;
- .button {
- width: 60px;
- height: 60px;
- background: linear-gradient(144deg, #00aefb 0%, #0076f6 100%);
- }
- .add-room-icon {
- font-size: 24px;
- }
- p {
- font-size: 14px;
- color: #333;
- margin-top: 10px;
- }
- }
- .goto-layer {
- position: fixed;
- left: 50%;
- transform: translateX(-50%);
- pointer-events: none;
- }
- .goto-top {
- pointer-events: all;
- right: 20px;
- bottom: 20px;
- background-color: #fff;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 8px;
- width: 60px;
- height: 60px;
- font-size: 24px;
- color: #747575;
- position: absolute;
- opacity: 0.5;
- transition: opacity 0.3s ease;
- cursor: pointer;
- &:hover {
- opacity: 1;
- }
- }
- .header-title-tab {
- display: flex;
- flex: 1;
- flex-direction: row;
- justify-content: space-between;
- padding-right: 30px;
- }
- </style>
- <style lang="scss">
- .room-search,
- .room-search input {
- background: #f7f8fa;
- }
- .select-group {
- .ant-radio-button-wrapper {
- &:nth-child(1) {
- border-top-left-radius: 15px;
- border-bottom-left-radius: 15px;
- }
- &:nth-child(3) {
- border-top-right-radius: 15px;
- border-bottom-right-radius: 15px;
- }
- }
- }
- .page-list {
- .ant-card {
- min-height: 332px;
- }
- }
- </style>
|