飞天云平台-国产化
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1216 lines
48 KiB

<template>
<div class="app-container row-container">
<!-- 标题设置 -->
<div class="config-title">
<p>大屏标题</p>
<el-tooltip v-if="!isEditable" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="title-readonly" @dblclick="handleTitleDblClick">
{{ screen_title }}
</span>
</el-tooltip>
<el-input v-else ref="titleInput" v-model="screen_title" style="width: 600px;" @blur="handleTitleBlur" @keyup.enter="handleTitleBlur" />
<div class="double-click-btn">
<i class="iconfont icon-zhuyi-lan" />
<span>注意:标题不要超过17个字,否则影响美观!</span>
</div>
<previewSetting ref="previewSettingRef" :preview-url-parent="previewUrlParent" @triggerInit="initScreenSetting" />
</div>
<!-- 屏幕内容设置 -->
<div class="config-screen">
<div
v-for="(item,index) in screenItems"
:key="item.id"
class="config-screen-item"
:class="{ 'active': activeTab === index }"
:data-index="index"
@click="handleTabClick(index)"
>
<img :src="require(`@/assets/images/screen/screen${item.id}.png`)" alt="">
<div class="screen-mask">
<div class="title-mask">{{ item.name }}</div>
<div class="screen-info">
<span>1920*1080</span>
<span>{{ index+1 }}</span>
</div>
<div class="screen-playOrPause">
<i :class="item.enabled ? 'el-icon-video-play' : 'el-icon-video-pause'" @click.stop="toggleScreenStatus(index)" />
</div>
<div class="screen-time">
<el-tooltip v-if="!item.editing" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="time-readonly" @click="handleTimeClick($event)" @dblclick="handleEditClick($event, item)">
{{ item.time }}
</span>
</el-tooltip>
<el-input v-else ref="timeInput" v-model="item.time" type="number" @blur="handleTimeBlur(item)" @keyup.enter="handleTimeBlur(item)" />
<span class="time-unit">秒</span>
</div>
</div>
</div>
<div class="screen-right-info">
<p>大屏启用<span style="color: #0348f3; font-weight: bold; padding: 0 4px;">{{ enabledCount }}</span>版,停用<span style="color: #ED4A41; font-weight: bold; padding: 0 4px;">{{ disabledCount }}</span>版,单次循环总时长<span style="color: #0348f3; font-weight: bold; padding: 0 4px;">{{ cycleTime }}</span>/秒</p>
<div style="padding-top: 6px; display: flex; justify-content: flex-start; align-items: flex-start;">
<span style="display: block;">注意:</span>
<p>单击可切换下方大屏编辑页;<br>长按拖动,编辑大屏播放顺序;<br>单击状态按钮可启用/停用大屏;<br>双击时长编辑框可编辑单个大屏播放时长;<br>至少开启1个大屏</p>
</div>
</div>
</div>
<transition name="tab-slide" mode="out-in">
<div :key="activeTab" class="content-area">
<!-- {{ currentScreenItem.name }}(ID: {{ currentScreenItem.id }})内容 - 这里是第{{ activeTab + 1 }}个大屏的详细配置 -->
<div>
<div class="screen-content-title">
<h4>{{ currentScreenItem.name }}</h4>
<el-tag v-if="currentScreenItem.enabled" type="success">已启用</el-tag>
<el-tag v-else type="danger">已停用</el-tag>
<p>第<span>{{ activeTab + 1 }}</span>屏 播放时长<span>{{ currentScreenItem.time }}</span>/秒</p>
</div>
<div class="screen-remarks">
<span>简介</span>
<p v-if="currentScreenItem.id === 1">{{ currentScreenItem.name }}为系统默认第1屏,主要显示数据包括(按从上到下,从左到右的顺序):到馆统计、藏书总量、累积办证、粉丝数量、累积借出、热门搜索、图书推荐、微信公众号二维码</p>
<p v-if="currentScreenItem.id === 2">{{ currentScreenItem.name }}为系统默认第2屏,主要显示数据包括(按从上到下,从左到右的顺序):总分馆介绍、区域地图及总分馆定位、读者统计、借阅Top10</p>
<p v-if="currentScreenItem.id === 3">{{ currentScreenItem.name }}为系统默认第3屏,主要显示数据包括(按从上到下,从左到右的顺序):本年累积借阅数量、今日借阅数量、今日借阅趋势、近7日借阅统计</p>
<p v-if="currentScreenItem.id === 4">{{ currentScreenItem.name }}为系统默认第4屏,主要显示数据包括(按从上到下,从左到右的顺序):宣传视频、重要通知、图书借阅排行榜、微信公众号二维码。</p>
<p v-if="currentScreenItem.id === 5">{{ currentScreenItem.name }}为系统默认第5屏,整屏显示宣传图片(支持多图片切换)。</p>
</div>
<div class="area-config">
<div v-if="currentScreenItem.id === 1" class="config-item">
<div class="config-item-main">
<span class="data-title">到馆统计</span>
<el-radio-group v-model="arrival_library_setting" aria-hidden="false" @change="handleArrivalSettingChange">
<el-radio label="1">本地数据</el-radio>
<el-radio label="2">基数计算</el-radio>
<el-radio label="3">第三方接口</el-radio>
</el-radio-group>
</div>
<div v-if="arrival_library_setting === '2'" class="library-form">
<!-- 原到馆统计表单 -->
<el-form ref="librarySettingForm" :model="librarySettingForm" :rules="rules" size="small" label-width="100px">
<el-form-item label="本年到馆" prop="visit_base">
<el-tooltip v-if="!editStatus.librarySettingForm.visit_base" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'visit_base')">
{{ librarySettingForm.visit_base }}
</span>
</el-tooltip>
<el-input v-else ref="librarySettingFormvisit_base" v-model="librarySettingForm.visit_base" type="number" @blur="handleBlur('librarySettingForm', 'visit_base')" @keyup.enter="handleBlur('librarySettingForm', 'visit_base')" />
<el-checkbox v-model="librarySettingForm.visit_base_checked" label="直接显示" name="visit_base_checked" @change="handleCheckboxChange('visit_base', $event)" />
</el-form-item>
<el-form-item label="去年到馆" prop="last_year_visit_base">
<el-tooltip v-if="!editStatus.librarySettingForm.last_year_visit_base" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'last_year_visit_base')">
{{ librarySettingForm.last_year_visit_base }}
</span>
</el-tooltip>
<el-input v-else ref="librarySettingFormlast_year_visit_base" v-model="librarySettingForm.last_year_visit_base" type="number" @blur="handleBlur('librarySettingForm', 'last_year_visit_base')" @keyup.enter="handleBlur('librarySettingForm', 'last_year_visit_base')" />
</el-form-item>
<el-form-item label="今日到馆" prop="today_visit">
<el-tooltip v-if="!editStatus.librarySettingForm.today_visit" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'today_visit')">
{{ librarySettingForm.today_visit }} </span>
</el-tooltip>
<el-input v-else ref="librarySettingFormtoday_visit" v-model="librarySettingForm.today_visit" type="number" @blur="handleBlur('librarySettingForm', 'today_visit')" @keyup.enter="handleBlur('librarySettingForm', 'today_visit')" />
<el-checkbox v-model="librarySettingForm.today_visit_checked" label="直接显示" name="today_visit_checked" @change="handleCheckboxChange('today_visit', $event)" />
</el-form-item>
<el-form-item label="昨日到馆" prop="yesterday_visit">
<el-tooltip v-if="!editStatus.librarySettingForm.yesterday_visit" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'yesterday_visit')"> {{ librarySettingForm.yesterday_visit }} </span>
</el-tooltip>
<el-input v-else ref="librarySettingFormyesterday_visit" v-model="librarySettingForm.yesterday_visit" type="number" @blur="handleBlur('librarySettingForm', 'yesterday_visit')" @keyup.enter="handleBlur('librarySettingForm', 'yesterday_visit')" />
<el-checkbox v-model="librarySettingForm.yesterday_visit_checked" label="直接显示" name="yesterday_visit_checked" @change="handleCheckboxChange('yesterday_visit', $event)" />
</el-form-item>
<el-form-item label="本月到馆" prop="this_month_visit">
<el-tooltip v-if="!editStatus.librarySettingForm.this_month_visit" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'this_month_visit')">
{{ librarySettingForm.this_month_visit }}
</span>
</el-tooltip>
<el-input v-else ref="librarySettingFormthis_month_visit" v-model="librarySettingForm.this_month_visit" type="number" @blur="handleBlur('librarySettingForm', 'this_month_visit')" @keyup.enter="handleBlur('librarySettingForm', 'this_month_visit')" />
<el-checkbox v-model="librarySettingForm.this_month_visit_checked" label="直接显示" name="this_month_visit_checked" @change="handleCheckboxChange('this_month_visit', $event)" />
</el-form-item>
<el-form-item label="上月到馆" prop="last_month_visit">
<el-tooltip v-if="!editStatus.librarySettingForm.last_month_visit" class="item" effect="dark" content="双击输入框进行编辑" placement="top">
<span class="edit-readonly" @dblclick="handleDblClick('librarySettingForm', 'last_month_visit')">
{{ librarySettingForm.last_month_visit }}
</span>
</el-tooltip>
<el-input v-else ref="librarySettingFormlast_month_visit" v-model="librarySettingForm.last_month_visit" type="number" @blur="handleBlur('librarySettingForm', 'last_month_visit')" @keyup.enter="handleBlur('librarySettingForm', 'last_month_visit')" />
<el-checkbox v-model="librarySettingForm.last_month_visit_checked" label="直接显示" name="last_month_visit" @change="handleCheckboxChange('last_month_visit', $event)" />
</el-form-item>
</el-form>
<div class="config-remarks">双击输入框可进行编辑,注意:<br>
如未勾选“直接显示”,系统根据“本年到馆”和“去年到馆”所填数量自动生成:今日到馆、昨日到馆、本月到馆、上月到馆<br>
若勾选了“直接显示”,系统会直接显示用户所填数量值(注意:未填写数量,则显示为“0”)
</div>
</div>
</div>
<div v-if="currentScreenItem.id !== 5" class="config-item">
<div class="config-item-main">
<span class="data-title">图创接口</span>
<!-- 原图创接口表单 -->
<el-form ref="openForm" :model="openForm" size="small" label-width="100px">
<el-form-item label="OpenLib地址" prop="open_lib_http">
<el-tooltip
v-if="!editStatus.openForm.open_lib_http"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('openForm', 'open_lib_http')"
>
{{ openForm.open_lib_http }}
</span>
</el-tooltip>
<el-input
v-else
ref="openFormopen_lib_http"
v-model="openForm.open_lib_http"
@blur="handleBlur('openForm', 'open_lib_http')"
@keyup.enter="handleBlur('openForm', 'open_lib_http')"
/>
</el-form-item>
<el-form-item label="AppId" prop="open_lib_appId">
<el-tooltip
v-if="!editStatus.openForm.open_lib_appId"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('openForm', 'open_lib_appId')"
>
{{ openForm.open_lib_appId }}
</span>
</el-tooltip>
<el-input
v-else
ref="openFormopen_lib_appId"
v-model="openForm.open_lib_appId"
@blur="handleBlur('openForm', 'open_lib_appId')"
@keyup.enter="handleBlur('openForm', 'open_lib_appId')"
/>
</el-form-item>
<el-form-item label="Secret" prop="open_lib_secret">
<el-tooltip
v-if="!editStatus.openForm.open_lib_secret"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('openForm', 'open_lib_secret')"
>
{{ openForm.open_lib_secret }}
</span>
</el-tooltip>
<el-input
v-else
ref="openFormopen_lib_secret"
v-model="openForm.open_lib_secret"
@blur="handleBlur('openForm', 'open_lib_secret')"
@keyup.enter="handleBlur('openForm', 'open_lib_secret')"
/>
</el-form-item>
</el-form>
</div>
<div class="config-remarks">双击输入框可进行编辑。数据将用于“总览屏”、“区域屏”、“统计屏”、“媒体屏”,在任意分屏编辑均可生效! </div>
</div>
<div v-if="currentScreenItem.id === 1" class="config-item">
<div class="config-item-main">
<span class="data-title">热门搜索</span>
<!-- 原热门搜索表单 -->
<el-form ref="hotForm" :model="hotForm" size="small" label-width="100px">
<el-form-item label="数据来源地址" prop="hot_search_http">
<el-tooltip
v-if="!editStatus.hotForm.hot_search_http"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('hotForm', 'hot_search_http')"
>
{{ hotForm.hot_search_http }}
</span>
</el-tooltip>
<el-input
v-else
ref="hotFormhot_search_http"
v-model="hotForm.hot_search_http"
@blur="handleBlur('hotForm', 'hot_search_http')"
@keyup.enter="handleBlur('hotForm', 'hot_search_http')"
/>
</el-form-item>
</el-form>
</div>
<div class="config-remarks">双击输入框可进行编辑。数据将用于“总览屏”。 </div>
</div>
<div v-if="currentScreenItem.id === 1" class="config-item">
<div class="config-item-main">
<span class="data-title">微信绑定</span>
<!-- 原微信绑定表单 -->
<el-form ref="vxForm" :model="vxForm" size="small" label-width="100px">
<el-form-item label="AppID" prop="vx_appID">
<el-tooltip
v-if="!editStatus.vxForm.vx_appID"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('vxForm', 'vx_appID')"
>
{{ vxForm.vx_appID }}
</span>
</el-tooltip>
<el-input
v-else
ref="vxFormvx_appID"
v-model="vxForm.vx_appID"
@blur="handleBlur('vxForm', 'vx_appID')"
@keyup.enter="handleBlur('vxForm', 'vx_appID')"
/>
</el-form-item>
<el-form-item label="AppSecret" prop="vx_AppSecret">
<el-tooltip
v-if="!editStatus.vxForm.vx_AppSecret"
class="item"
effect="dark"
content="双击输入框进行编辑"
placement="top"
>
<span
class="edit-readonly"
@dblclick="handleDblClick('vxForm', 'vx_AppSecret')"
>
{{ vxForm.vx_AppSecret }}
</span>
</el-tooltip>
<el-input
v-else
ref="vxFormvx_AppSecret"
v-model="vxForm.vx_AppSecret"
@blur="handleBlur('vxForm', 'vx_AppSecret')"
@keyup.enter="handleBlur('vxForm', 'vx_AppSecret')"
/>
</el-form-item>
</el-form>
</div>
<div class="config-remarks">双击输入框可进行编辑。图书馆公众号AppID、AppSecrect 仅用于“总览屏”显示公众号粉丝数量。</div>
</div>
<wecharQrCode v-if="currentScreenItem.id === 1 || currentScreenItem.id === 4" ref="wecharQrCodeRef" :qr-code-url="wecharQrCodeUrl" @triggerInit="initScreenSetting" @ready="onWechatQrCodeReady" />
<bookRecommend v-if="currentScreenItem.id === 1" ref="bookRecommendRef" @ready="initScreenBookRecommend" />
<areaSetting v-if="currentScreenItem.id === 2" ref="areaSettingRef" :map-data="mapData" @triggerInit="initScreenSetting" @ready="initScreenBranch" />
<mediaSetting v-if="currentScreenItem.id === 4" ref="mediaSettingRef" @ready="initScreenNotice" />
<advSetting v-if="currentScreenItem.id === 5" ref="advSettingRef" :welcome-play="welcomePlay" @triggerInit="initScreenSetting" @ready="initScreenWelcomePromotion" />
</div>
</div>
</div>
</transition>
</div>
</template>
<script>
import { FetchInitScreenSetting, FetchEditScreenSetting } from '@/api/digitalScreen/index'
import Sortable from 'sortablejs'
import previewSetting from './module/previewSetting'
import wecharQrCode from './module/wecharQrCode'
import bookRecommend from './module/bookRecommend'
import areaSetting from './module/areaSetting'
import mediaSetting from './module/mediaSetting'
import advSetting from './module/advSetting'
import { mapGetters } from 'vuex'
export default {
name: 'DigitalScreen',
components: {
previewSetting,
wecharQrCode,
bookRecommend,
areaSetting,
mediaSetting,
advSetting
},
data() {
return {
tabPosition: 'top',
screen_title: '',
isEditable: false,
originalTitle: '',
activeTab: 0,
screenItems: [
{ id: 1, time: '5', name: '总览屏', enabled: true, editing: false, originalTime: '5', code: 'show1' },
{ id: 2, time: '5', name: '区域屏', enabled: true, editing: false, originalTime: '5', code: 'show2' },
{ id: 3, time: '5', name: '统计屏', enabled: true, editing: false, originalTime: '5', code: 'show3' },
{ id: 4, time: '5', name: '媒体屏', enabled: true, editing: false, originalTime: '5', code: 'show4' },
{ id: 5, time: '5', name: '欢迎屏', enabled: true, editing: false, originalTime: '5', code: 'show5' }
],
editingLock: false,
prevActiveTab: 0,
clickTimer: null, // 用于判断单击/双击的计时器
isDoubleClick: false,
// 到馆统计
arrival_library_setting: '1',
librarySettingForm: {
visit_base: null,
remarks: null,
last_year_visit_base: null,
today_visit: null,
yesterday_visit: null,
this_month_visit: null,
last_month_visit: null
},
openForm: {
open_lib_http: null,
open_lib_appId: null,
open_lib_secret: null
},
hotForm: {
hot_search_http: null
},
vxForm: {
vx_appID: null,
vx_AppSecret: null
},
wecharQrCodeUrl: null,
mapData: null,
welcomePlay: null,
previewUrlParent: null,
editStatus: {
openForm: {
open_lib_http: false,
open_lib_appId: false,
open_lib_secret: false
},
hotForm: {
hot_search_http: false
},
vxForm: {
vx_appID: false,
vx_AppSecret: false
},
librarySettingForm: {
// 基础属性(已有的)
visit_base: null,
last_year_visit_base: null,
today_visit: null,
yesterday_visit: null,
this_month_visit: null,
last_month_visit: null,
visit_base_checked: false, // 对应“本年到馆”的“直接显示”
today_visit_checked: false, // 对应“今日到馆”的“直接显示”
yesterday_visit_checked: false, // 对应“昨日到馆”的“直接显示”
this_month_visit_checked: false, // 对应“本月到馆”的“直接显示”
last_month_visit_checked: false // 对应“上月到馆”的“直接显示”
}
},
originalValues: {
title: '',
openForm: {},
hotForm: {},
vxForm: {},
librarySettingForm: {},
specialFields: {}
},
rules: {
visit_base: [
{ required: true, message: '本年累计到馆不可为空', trigger: 'blur' }
],
last_year_visit_base: [
{ required: true, message: '去年到馆不可为空', trigger: 'blur' }
]
}
}
},
computed: {
...mapGetters([
'baseApi',
'user'
]),
enabledCount() {
return this.screenItems.filter(item => item.enabled).length
},
disabledCount() {
return this.screenItems.filter(item => !item.enabled).length
},
cycleTime() {
return this.screenItems.reduce((total, item) => {
return item.enabled ? total + (parseInt(item.time) || 0) : total
}, 0)
},
currentScreenItem() {
return this.screenItems[this.activeTab]
}
},
created() {
this.initTitle()
},
mounted() {
this.$nextTick(() => {
this.initScreenSetting()
this.draggableScreen()
})
},
methods: {
initScreenWelcomePromotion() {
this.$refs.advSettingRef.initScreenWelcomePromotion()
if (this.$refs.advSettingRef) {
this.$refs.advSettingRef.updateSwiper()
}
},
initScreenNotice() {
this.$refs.mediaSettingRef.initScreenNotice()
this.$refs.mediaSettingRef.initScreenVideo()
},
initScreenBranch() {
this.$refs.areaSettingRef.initScreenBranch()
},
initScreenBookRecommend() {
this.$refs.bookRecommendRef.initScreenBookRecommend()
if (this.$refs.bookRecommendRef) {
this.$refs.bookRecommendRef.updateBookSwiper()
}
},
onWechatQrCodeReady() {
this.$refs.wecharQrCodeRef.reloadImage()
},
// 初始化智慧大屏基本数据
initScreenSetting() {
FetchInitScreenSetting({ 'libcode': this.user.fonds.fondsNo }).then(res => {
const showScreenItem = Object.values(res).find(item => item.code === 'show_screen')
if (showScreenItem) {
// 处理显示状态(context)
if (showScreenItem.context) {
const enabledIds = showScreenItem.context.split(',').map(Number)
this.screenItems.forEach(item => {
item.enabled = enabledIds.includes(item.id)
})
}
// 处理显示顺序(remarks)
if (showScreenItem.remarks) {
const orderIds = showScreenItem.remarks.split(',').map(Number)
// 按照remarks指定的顺序重新排列screenItems
this.screenItems.sort((a, b) => {
return orderIds.indexOf(a.id) - orderIds.indexOf(b.id)
})
}
}
Object.values(res).forEach(item => {
const { code, context } = item
// 处理标题
if (code === 'screen_title') {
this.screen_title = context
this.originalTitle = this.screen_title
this.originalValues.title = this.screen_title
return
}
// 处理到馆统计相关
if (code === 'arrival_library_setting') {
this.arrival_library_setting = context
return
}
// 处理各个屏幕的显示时间(show1-show5)
if (code.startsWith('show') && !isNaN(parseInt(code.replace('show', '')))) {
const screenId = parseInt(code.replace('show', ''))
const screenItem = this.screenItems.find(item => item.id === screenId)
if (screenItem) {
screenItem.time = context || '5' // 默认5秒
screenItem.originalTime = screenItem.time // 同步originalTime
}
return
}
// 处理到馆统计表单字段
if (['visit_base', 'last_year_visit_base', 'today_visit', 'yesterday_visit', 'this_month_visit', 'last_month_visit'].includes(code)) {
this.$set(this.librarySettingForm, code, context)
return
}
// 处理图创接口相关
if (code === 'open_lib_http') {
this.openForm.open_lib_http = context
} else if (code === 'open_lib_appId') {
this.openForm.open_lib_appId = context
} else if (code === 'open_lib_secret') {
this.openForm.open_lib_secret = context
}
// 处理热门搜索相关
if (code === 'hot_search_http') {
this.hotForm.hot_search_http = context
}
// 处理微信绑定相关
if (code === 'vx_appID') {
this.vxForm.vx_appID = context
} else if (code === 'vx_AppSecret') {
this.vxForm.vx_AppSecret = context
}
// 处理公众号二维码
if (code === 'wechar_qr_code') {
this.wecharQrCodeUrl = context
}
if (code === 'map_data') {
this.mapData = context
}
if (code === 'welcome_play') {
this.welcomePlay = context
}
if (code === 'preview_url') {
this.previewUrlParent = context
}
})
Object.values(res).forEach(item => {
const { code, context, remarks } = item
if (['visit_base', 'today_visit', 'yesterday_visit', 'this_month_visit', 'last_month_visit'].includes(code)) {
this.$set(this.librarySettingForm, code, context)
this.$set(this.librarySettingForm, `${code}_checked`, remarks === '1')
}
})
}).catch(() => {
})
},
// 大屏标题
initTitle() {
this.screen_title = '' // 默认空字符串
this.originalTitle = this.screen_title
this.originalValues.title = this.screen_title
},
handleTitleDblClick() {
this.isEditable = true
this.originalTitle = this.screen_title
this.originalValues.title = this.screen_title
this.$nextTick(() => {
const titleInput = this.$refs.titleInput
if (titleInput) {
titleInput.focus()
}
})
},
handleTitleBlur() {
this.isEditable = false
if (this.screen_title.length > 17) {
this.$message.warning('标题不能超过17个字,请修改!')
this.screen_title = this.originalTitle
return
}
if (this.screen_title !== this.originalTitle) {
this.saveEdit('title', 'screen_title')
}
},
handleTabClick(index) {
// 如果是双击事件,则不执行Tab切换
if (this.isDoubleClick) {
this.isDoubleClick = false
return
}
this.prevActiveTab = this.activeTab
this.activeTab = index
this.$nextTick(() => {
if (this.currentScreenItem && this.currentScreenItem.id === 1) {
if (this.$refs.bookRecommendRef) {
this.$refs.bookRecommendRef.updateBookSwiper()
}
} else if (this.currentScreenItem && this.currentScreenItem.id === 5) {
if (this.$refs.advSettingRef) {
this.$refs.advSettingRef.updateSwiper()
}
}
})
},
// handleTabClick(index) {
// if (this.isDoubleClick) {
// this.isDoubleClick = false
// return
// }
// const prevTab = this.activeTab
// this.activeTab = index
// if (prevTab === index) {
// return
// }
// this.$nextTick(() => {
// const currentId = this.currentScreenItem?.id
// if (!currentId) return
// switch (currentId) {
// case 1:
// this.handleScreen1()
// break
// case 4:
// this.handleScreen4()
// break
// case 5:
// this.handleScreen5()
// break
// }
// })
// },
// // 处理ID=1的屏幕(总览屏)
// handleScreen1() {
// if (this.$refs.bookRecommendRef) {
// this.$refs.bookRecommendRef.updateBookSwiper()
// } else {
// console.warn('bookRecommend组件未渲染(ID=1屏幕)')
// }
// this.refreshWechatQrCode()
// },
// // 处理ID=1的屏幕
// handleScreen4() {
// this.refreshWechatQrCode()
// },
// // 处理ID=5的屏幕(欢迎屏)
// handleScreen5() {
// if (this.$refs.advSettingRef) {
// this.$refs.advSettingRef.updateSwiper()
// } else {
// console.warn('advSetting组件未渲染(ID=5屏幕)')
// }
// },
// refreshWechatQrCode() {
// if (this.$refs.wecharQrCodeRef) {
// this.$refs.wecharQrCodeRef.reloadImage()
// } else {
// console.log('wecharQrCode组件尚未渲染或无需渲染')
// }
// },
// 大屏是否启用 - 修改后也需要提交show_screen
toggleScreenStatus(index) {
const currentEnabledCount = this.enabledCount
if (this.screenItems[index].enabled && currentEnabledCount <= 1) {
this.$message.warning('至少需要启用一个大屏')
return
}
// 正常切换状态
this.screenItems[index].enabled = !this.screenItems[index].enabled
const statusText = this.screenItems[index].enabled ? '启用' : '停用'
this.$message.info(`大屏${index + 1}-即${this.screenItems[index].name}已${statusText}`)
this.submitScreenOrderAndStatus()
},
// 大屏拖拽排序
draggableScreen() {
const container = document.querySelector('.config-screen')
const that = this
let originalOrder = [...this.screenItems.map(item => item.id)]
Sortable.create(container, {
draggable: '.config-screen-item',
animation: 150,
onStart() {
originalOrder = [...that.screenItems.map(item => item.id)]
},
onEnd({ newIndex, oldIndex }) {
if (newIndex === oldIndex) return
const activeItemId = that.screenItems[that.activeTab].id
// 执行元素移动操作
const movedItem = that.screenItems.splice(oldIndex, 1)[0]
that.screenItems.splice(newIndex, 0, movedItem)
// 查找原激活项在新数组中的索引
const newActiveIndex = that.screenItems.findIndex(item => item.id === activeItemId)
if (newActiveIndex !== -1) {
that.activeTab = newActiveIndex
}
// 检查顺序是否真的发生了变化
const newOrder = [...that.screenItems.map(item => item.id)]
if (!that.arraysEqual(originalOrder, newOrder)) {
// 顺序变化,提交show_screen数据
that.submitScreenOrderAndStatus()
}
}
})
},
// 辅助方法:判断两个数组是否相等
arraysEqual(arr1, arr2) {
if (arr1.length !== arr2.length) return false
for (let i = 0; i < arr1.length; i++) {
if (arr1[i] !== arr2[i]) return false
}
return true
},
// 提交屏幕顺序和状态到show_screen
submitScreenOrderAndStatus() {
// 1. 收集显示的屏幕ID(enabled为true的)
const enabledIds = this.screenItems
.filter(item => item.enabled)
.map(item => item.id)
.join(',')
// 2. 收集所有屏幕的顺序(无论是否启用)
const orderIds = this.screenItems
.map(item => item.id)
.join(',')
// 3. 调用saveEdit提交,使用specialFields表单类型
const formName = 'specialFields'
const field = 'show_screen'
// 记录原始值用于可能的回滚
if (!this.originalValues[formName]) {
this.originalValues[formName] = {}
}
this.originalValues[formName][field] = {
context: enabledIds,
remarks: orderIds
}
// 调用saveEdit提交
this.saveEdit(formName, field)
},
// 大屏展示时间操作
handleTimeClick(event) {
// 阻止事件冒泡
event.stopPropagation()
// 清除之前的计时器
if (this.clickTimer) {
clearTimeout(this.clickTimer)
}
// 设置新计时器,300ms内无第二次点击则视为单击
this.clickTimer = setTimeout(() => {
this.isDoubleClick = false
}, 300)
},
handleEditClick(event, item) {
event.stopPropagation()
this.isDoubleClick = true
if (!item) {
console.warn('item is undefined')
return
}
if (this.editingLock) {
return
}
this.editingLock = true
setTimeout(() => {
this.editingLock = false
}, 300)
try {
this.enableEdit(item)
} catch (error) {
console.error(error)
}
},
enableEdit(item) {
item.editing = true
item.originalTime = item.time
this.$nextTick(() => {
const input = this.$refs.timeInput.find(ref => ref && ref.$el)
if (input) {
input.focus()
setTimeout(() => {
input.select()
}, 0)
}
})
},
handleTimeBlur(item) {
// 验证时长有效性
if (item.time === '' || isNaN(item.time) || parseInt(item.time) <= 0) {
this.$message.warning('播放时长必须为大于0的数字')
item.time = item.originalTime
} else {
// 转换为整数字符串(避免出现小数)
item.time = parseInt(item.time).toString()
// 只有当值发生变化时才提交
if (item.time !== item.originalTime) {
this.submitScreenTime(item)
}
}
item.editing = false
},
// 提交屏幕时长到对应show1-show5
submitScreenTime(item) {
// 使用specialFields表单类型
const formName = 'specialFields'
const field = item.code
// 记录原始值用于可能的回滚
if (!this.originalValues[formName]) {
this.originalValues[formName] = {}
}
this.originalValues[formName][field] = item.originalTime
// 调用saveEdit提交
this.saveEdit(formName, field)
},
// 其他表单编辑框
handleDblClick(formName, field) {
this.originalValues[formName][field] = this[formName][field]
this.editStatus[formName][field] = true
this.$nextTick(() => {
const input = this.$refs[`${formName}${field}`]
if (input) input.focus()
})
},
handleBlur(formName, field) {
this.editStatus[formName][field] = false
if (this[formName][field] !== this.originalValues[formName][field]) {
this.saveEdit(formName, field)
}
},
// 处理到馆统计设置变更
handleArrivalSettingChange(newValue) {
const virtualFormName = 'specialFields'
const field = 'arrival_library_setting'
// 初始化原始值(仅首次)
if (!this.originalValues[virtualFormName]) {
this.originalValues[virtualFormName] = {}
}
if (this.originalValues[virtualFormName][field] === undefined) {
this.originalValues[virtualFormName][field] = this.arrival_library_setting
}
this.saveEdit(virtualFormName, field)
},
handleCheckboxChange(field, checked) {
this.$set(this.librarySettingForm, `${field}_checked`, checked)
this.saveEdit('librarySettingForm', field)
},
saveEdit(formName, field) {
let code = field
let context
let remarks = ''
// 处理标题特殊情况
if (formName === 'title') {
code = 'screen_title'
context = this.screen_title
} else if (formName === 'specialFields' && field === 'show_screen') {
// 处理show_screen特殊情况
context = this.originalValues[formName][field].context
remarks = this.originalValues[formName][field].remarks
} else if (formName === 'specialFields' && field.startsWith('show')) {
// 处理show1-show5时长提交
// 从screenItems中找到对应的屏幕获取time
const screenItem = this.screenItems.find(item => item.code === field)
context = screenItem ? screenItem.time : '5' // 默认5秒
} else if (formName === 'specialFields') {
// 处理其他特殊字段(如arrival_library_setting)
context = this[field]
} else {
// 处理普通表单字段
context = this[formName][field]
if (formName === 'librarySettingForm') {
remarks = this[formName][`${field}_checked`] ? '1' : '0'
}
}
// 2. 校验必填项和特殊规则
// 对于show_screen,至少需要启用一个屏幕
if (formName === 'specialFields' && field === 'show_screen') {
if (!context) {
this.$message.warning('至少需要启用一个大屏')
return
}
} else if (formName === 'specialFields' && field.startsWith('show')) {
// 对于show1-show5,校验时长有效性
if (!context || isNaN(context) || parseInt(context) <= 0) {
this.$message.warning('播放时长必须为大于0的数字')
this.rollbackValue(formName, field)
return
}
} else if (!context && context !== 0) {
// 其他字段的非空校验
this.$message.warning(`${this.getFieldLabel(formName, field)}不能为空`)
this.rollbackValue(formName, field)
return
}
// 3. 构建提交参数
const submitParam = { code, context, remarks }
// 4. 调用接口保存
FetchEditScreenSetting(submitParam)
.then(() => {
this.$message.success(`${this.getFieldLabel(formName, field)}更新成功`)
// 更新原始值为新值
if (formName === 'title') {
this.originalTitle = this.screen_title
this.originalValues.title = this.screen_title
} else if (formName === 'specialFields' && field.startsWith('show') && field !== 'show_screen') {
// 更新屏幕的originalTime
const screenItem = this.screenItems.find(item => item.code === field)
if (screenItem) {
screenItem.originalTime = context
}
this.originalValues[formName][field] = context
} else if (formName !== 'specialFields' || field !== 'show_screen') {
this.originalValues[formName][field] = context
}
})
.catch(() => {
this.$message.error(`${this.getFieldLabel(formName, field)}更新失败`)
this.rollbackValue(formName, field)
})
},
// 新增:回滚值的通用方法
rollbackValue(formName, field) {
if (this.originalValues[formName]?.[field] !== undefined) {
if (formName === 'title') {
this.screen_title = this.originalValues[formName][field]
} else if (formName === 'specialFields' && field.startsWith('show') && field !== 'show_screen') {
// 回滚屏幕时长
const screenItem = this.screenItems.find(item => item.code === field)
if (screenItem) {
screenItem.time = this.originalValues[formName][field]
screenItem.originalTime = this.originalValues[formName][field]
}
} else if (formName === 'specialFields') {
this[field] = this.originalValues[formName][field]
} else {
this[formName][field] = this.originalValues[formName][field]
// 回滚复选框状态
if (formName === 'librarySettingForm') {
const originalChecked = this.originalValues[formName][`${field}_checked`]
if (originalChecked !== undefined) {
this[formName][`${field}_checked`] = originalChecked
}
}
}
}
},
getFieldLabel(formName, field) {
const labels = {
title: {
screen_title: '大屏标题'
},
specialFields: {
arrival_library_setting: '到馆统计设置',
show_screen: '大屏显示设置',
show1: '总览屏播放时长',
show2: '区域屏播放时长',
show3: '统计屏播放时长',
show4: '媒体屏播放时长',
show5: '欢迎屏播放时长'
},
openForm: {
open_lib_http: 'OpenLib地址',
open_lib_appId: 'AppId',
open_lib_secret: 'Secret'
},
hotForm: {
hot_search_http: '数据来源地址'
},
vxForm: {
vx_appID: '微信AppID',
vx_AppSecret: '微信AppSecret'
},
librarySettingForm: {
visit_base: '本年到馆',
last_year_visit_base: '去年到馆',
today_visit: '今日到馆',
yesterday_visit: '昨日到馆',
this_month_visit: '本月到馆',
last_month_visit: '上月到馆'
}
}
return labels[formName][field] || field
}
}
}
</script>
<style scoped lang="scss">
@import "~@/assets/styles/digitalScreen.scss";
.config-screen{
display: flex;
justify-content: flex-start;
align-items: flex-end;
padding: 12px 0 20px 0;
position: relative;
border-top: 1px solid #ebeef5;
height: 175px;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
height: 4px;
background-color: #0348f3;
border-radius: 2px 2px 0 0;
transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1); // 平滑过渡动画
z-index: 1;
width: 242px;
left: 0;
transform: translateX(calc(256px * var(--active-index, 0))); // 242px + 14px间距
}
.config-screen-item{
position: relative;
width: 242px;
margin-right: 12px;
cursor: pointer;
transition: all 0.3s ease; // 选中状态过渡
z-index: 2; // 确保内容在蓝色条上方
.screen-mask{
position: relative;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background:rgba(0,0,0,0.4);
.title-mask{
text-align: center;
font-weight: bold;
color: #fff;
letter-spacing: 3px;
}
}
&.active {
transform: translateY(-5px); // 上浮效果
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); // 阴影效果
border-radius: 4px;
// overflow: hidden;
}
img{
display: block;
height: 136px;
width: 100%;
}
.screen-info{
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: space-between;
width: 100%;
padding: 6px;
font-size: 12px;
color: #fff;
span{
display: block;
}
}
.screen-playOrPause{
position: absolute;
left: 6px;
bottom: 4px;
font-size: 30px;
.el-icon-video-play{
color: #12C47A;
}
.el-icon-video-pause{
color: #ED4A41;
}
}
.screen-time{
position: absolute;
right: 8px;
bottom: 8px;
align-items: center;
color: #fff;
.time-readonly {
display: inline-block;
width: 40px;
height: 26px;
line-height: 26px;
text-align: center;
border-radius: 2px;
background-color: #fff;
font-size: 13px;
color: #606266;
cursor: default;
border: 1px solid #dcdfe6;
box-sizing: border-box;
}
::v-deep .el-input {
width: 40px;
.el-input__inner{
height: 26px;
line-height: 26px;
text-align: center;
padding: 0 4px;
border-radius: 2px;
}
}
span.time-unit{
display: inline-block;
font-size: 12px;
}
}
}
.screen-right-info{
flex: 1;
padding: 8px;
background-color: #EEF5FE;
color: #545B65;
font-size: 12px;
line-height: 20px;
border-left: 3px solid #0348F3;
.iconfont::before{
margin-top: 5px;
}
}
}
// 内容区域样式 + 过渡动画
.content-area {
height: 510px;
border-radius: 4px;
width: 100%;
overflow-y: scroll;
}
// 左右切换动画
.tab-slide-enter-active,
.tab-slide-leave-active {
transition: transform 0.5s ease, opacity 0.5s ease;
}
.tab-slide-enter-from {
transform: translateX(50px);
opacity: 0;
}
.tab-slide-leave-to {
transform: translateX(-50px);
opacity: 0;
}
// 监听activeTab变化更新CSS变量
::v-deep .config-screen {
--active-index: v-bind(activeTab);
}
</style>