Selaa lähdekoodia

Merge branch 'master' of http://121.36.46.135:3000/mes-ahdy/mescloud

hfy 4 kuukautta sitten
vanhempi
commit
46a6111ad6

+ 18 - 0
src/main/java/com/jeesite/modules/mes/dao/MesScreenConfigDao.java

@@ -0,0 +1,18 @@
+package com.jeesite.modules.mes.dao;
+
+import com.jeesite.common.dao.CrudDao;
+import com.jeesite.common.mybatis.annotation.MyBatisDao;
+import com.jeesite.modules.mes.entity.MesScreenConfig;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 大屏配置DAO接口
+ * @author hzd
+ */
+@MyBatisDao
+public interface MesScreenConfigDao extends CrudDao<MesScreenConfig> {
+
+    List<MesScreenConfig> findEnabledList(@Param("isEnabled") String isEnabled);
+}

+ 108 - 0
src/main/java/com/jeesite/modules/mes/entity/MesScreenConfig.java

@@ -0,0 +1,108 @@
+package com.jeesite.modules.mes.entity;
+
+import com.jeesite.common.entity.DataEntity;
+import com.jeesite.common.mybatis.annotation.Column;
+import com.jeesite.common.mybatis.annotation.Table;
+import com.jeesite.common.mybatis.mapper.query.QueryType;
+
+@Table(name="mes_screen_config", alias="a", label="大屏配置", columns={
+		@Column(name="id", attrName="id", label="主键", isPK=true),
+		@Column(name="screen_name", attrName="screenName", label="大屏名称", isQuery=true, queryType= QueryType.LIKE),
+		@Column(name="screen_code", attrName="screenCode", label="大屏编码", isQuery=true, queryType=QueryType.LIKE),
+		@Column(name="screen_url", attrName="screenUrl", label="大屏URL"),
+		@Column(name="screen_type", attrName="screenType", label="大屏类型"),
+		@Column(name="play_duration", attrName="playDuration", label="轮播时长(秒)"),
+		@Column(name="sort_order", attrName="sortOrder", label="排序"),
+		@Column(name="is_enabled", attrName="isEnabled", label="是否启用"),
+		@Column(name="remarks", attrName="remarks", label="备注"),
+		@Column(name="create_by", attrName="createBy", label="创建人", isUpdate=false, isQuery=false),
+		@Column(name="create_date", attrName="createDate", label="创建日期", isUpdate=false, isQuery=false, isUpdateForce=true),
+		@Column(name="update_by", attrName="updateBy", label="更新人", isQuery=false),
+		@Column(name="update_date", attrName="updateDate", label="更新日期", isQuery=false, isUpdateForce=true),
+	}, orderBy="a.sort_order ASC"
+)
+public class MesScreenConfig extends DataEntity<MesScreenConfig> {
+
+	private static final long serialVersionUID = 1L;
+
+	private String screenName;
+	private String screenCode;
+	private String screenUrl;
+	private String screenType;
+	private Integer playDuration;
+	private Integer sortOrder;
+	private String isEnabled;
+	private String remarks;
+
+	public MesScreenConfig() {
+		this(null);
+	}
+
+	public MesScreenConfig(String id){
+		super(id);
+	}
+
+	public String getScreenName() {
+		return screenName;
+	}
+
+	public void setScreenName(String screenName) {
+		this.screenName = screenName;
+	}
+
+	public String getScreenCode() {
+		return screenCode;
+	}
+
+	public void setScreenCode(String screenCode) {
+		this.screenCode = screenCode;
+	}
+
+	public String getScreenUrl() {
+		return screenUrl;
+	}
+
+	public void setScreenUrl(String screenUrl) {
+		this.screenUrl = screenUrl;
+	}
+
+	public String getScreenType() {
+		return screenType;
+	}
+
+	public void setScreenType(String screenType) {
+		this.screenType = screenType;
+	}
+
+	public Integer getPlayDuration() {
+		return playDuration;
+	}
+
+	public void setPlayDuration(Integer playDuration) {
+		this.playDuration = playDuration;
+	}
+
+	public Integer getSortOrder() {
+		return sortOrder;
+	}
+
+	public void setSortOrder(Integer sortOrder) {
+		this.sortOrder = sortOrder;
+	}
+
+	public String getIsEnabled() {
+		return isEnabled;
+	}
+
+	public void setIsEnabled(String isEnabled) {
+		this.isEnabled = isEnabled;
+	}
+
+	public String getRemarks() {
+		return remarks;
+	}
+
+	public void setRemarks(String remarks) {
+		this.remarks = remarks;
+	}
+}

+ 59 - 0
src/main/java/com/jeesite/modules/mes/service/MesScreenConfigService.java

@@ -0,0 +1,59 @@
+package com.jeesite.modules.mes.service;
+
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.service.CrudService;
+import com.jeesite.modules.mes.dao.MesScreenConfigDao;
+import com.jeesite.modules.mes.entity.MesScreenConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * 大屏配置Service
+ * @author hzd
+ */
+@Service
+public class MesScreenConfigService extends CrudService<MesScreenConfigDao, MesScreenConfig> {
+
+	@Autowired
+	private MesScreenConfigDao mesScreenConfigDao;
+
+	@Override
+	public MesScreenConfig get(MesScreenConfig mesScreenConfig) {
+		return super.get(mesScreenConfig);
+	}
+
+	@Override
+	public Page<MesScreenConfig> findPage(MesScreenConfig mesScreenConfig) {
+		return super.findPage(mesScreenConfig);
+	}
+
+	@Override
+	public List<MesScreenConfig> findList(MesScreenConfig mesScreenConfig) {
+		return super.findList(mesScreenConfig);
+	}
+
+	@Override
+	@Transactional
+	public void save(MesScreenConfig mesScreenConfig) {
+		super.save(mesScreenConfig);
+	}
+
+	@Override
+	@Transactional
+	public void updateStatus(MesScreenConfig mesScreenConfig) {
+		super.updateStatus(mesScreenConfig);
+	}
+
+	@Override
+	@Transactional
+	public void delete(MesScreenConfig mesScreenConfig) {
+		super.delete(mesScreenConfig);
+	}
+
+	public List<MesScreenConfig> findEnabledList() {
+		return dao.findEnabledList("1");
+	}
+}

+ 96 - 0
src/main/java/com/jeesite/modules/mes/web/MesScreenConfigController.java

@@ -0,0 +1,96 @@
+package com.jeesite.modules.mes.web;
+
+import com.jeesite.common.config.Global;
+import com.jeesite.common.entity.Page;
+import com.jeesite.common.web.BaseController;
+import com.jeesite.modules.mes.entity.MesScreenConfig;
+import com.jeesite.modules.mes.service.MesScreenConfigService;
+import com.jeesite.modules.mes.resp.CommonResp;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 大屏配置Controller
+ * @author hzd
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/mes/mesScreenConfig")
+public class MesScreenConfigController extends BaseController {
+
+	@Autowired
+	private MesScreenConfigService mesScreenConfigService;
+
+	@ModelAttribute
+	public MesScreenConfig get(String id, boolean isNewRecord) {
+		return mesScreenConfigService.get(id, isNewRecord);
+	}
+
+	@RequiresPermissions("mes:mesScreenConfig:view")
+	@RequestMapping(value = {"list", ""})
+	public String list(MesScreenConfig mesScreenConfig, Model model) {
+		model.addAttribute("mesScreenConfig", mesScreenConfig);
+		return "modules/mes/mesScreenConfigList";
+	}
+
+	@RequiresPermissions("mes:mesScreenConfig:view")
+	@RequestMapping(value = "listData")
+	@ResponseBody
+	public Page<MesScreenConfig> listData(MesScreenConfig mesScreenConfig, HttpServletRequest request, HttpServletResponse response) {
+		mesScreenConfig.setPage(new Page<>(request, response));
+		Page<MesScreenConfig> page = mesScreenConfigService.findPage(mesScreenConfig);
+		return page;
+	}
+
+	@RequiresPermissions("mes:mesScreenConfig:view")
+	@RequestMapping(value = "form")
+	public String form(MesScreenConfig mesScreenConfig, Model model) {
+		model.addAttribute("mesScreenConfig", mesScreenConfig);
+		return "modules/mes/mesScreenConfigForm";
+	}
+
+	@RequiresPermissions("mes:mesScreenConfig:edit")
+	@PostMapping(value = "save")
+	@ResponseBody
+	public String save(@Validated MesScreenConfig mesScreenConfig) {
+		mesScreenConfigService.save(mesScreenConfig);
+		return renderResult(Global.TRUE, text("保存大屏配置成功!"));
+	}
+
+	@RequiresPermissions("mes:mesScreenConfig:edit")
+	@RequestMapping(value = "delete")
+	@ResponseBody
+	public String delete(MesScreenConfig mesScreenConfig) {
+		mesScreenConfigService.delete(mesScreenConfig);
+		return renderResult(Global.TRUE, text("删除大屏配置成功!"));
+	}
+
+	@RequestMapping(value = "player")
+	public String player(Model model) {
+		return "modules/mes/mesScreenPlayer";
+	}
+
+	@RequestMapping(value = "getScreenList")
+	@ResponseBody
+	public CommonResp<List<MesScreenConfig>> getScreenList() {
+		CommonResp<List<MesScreenConfig>> resp = new CommonResp<>();
+		List<MesScreenConfig> list = mesScreenConfigService.findEnabledList();
+		resp.setData(list);
+		resp.setResult(Global.TRUE);
+		return resp;
+	}
+}

+ 5 - 3
src/main/resources/config/application.yml

@@ -56,13 +56,13 @@ jdbc:
   # Mysql 数据库配置
   type: mysql
   driver: com.mysql.cj.jdbc.Driver
- # url: jdbc:mysql://127.0.0.1:3306/mes_cloud_dy?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
+#  url: jdbc:mysql://127.0.0.1:3306/mes_cloud_dy?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
 #  url: jdbc:mysql://127.0.0.1:3306/mes_cloude_npd?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
   url: jdbc:mysql://192.168.9.181:3306/mes_cloud?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
   username: mes_cloud
   password: s2ENj7KaEySTC7dW
-  #username: root
- # password: 123456
+#  username: root
+#  password: root
   testSql: SELECT 1
 
   #  # Oracle 数据库配置(若使用 12c,请修改 /modules/core/pom.xml 文件,打开 12c 依赖,去掉 11g 依赖)
@@ -692,6 +692,8 @@ shiro:
     ${adminPath}/mes/mesGlueRecord/edit = anon
     ${adminPath}/mes/mesProductDbjBind/dbjBind = anon
     ${adminPath}/mes/mesGlueRecord/editSave = anon
+    ${adminPath}/mes/mesScreenConfig/getScreenList = anon
+    ${adminPath}/mes/mesScreenConfig/player = anon
     ${adminPath}/mes/mesProductRecord/select = anon
     ${adminPath}/mes/mesProductRecord/submit = anon
     ${adminPath}/mes/mesProductWsn/createSn = anon

+ 25 - 0
src/main/resources/mappings/modules/mes/MesScreenConfigDao.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeesite.modules.mes.dao.MesScreenConfigDao">
+
+	<select id="findEnabledList" resultType="com.jeesite.modules.mes.entity.MesScreenConfig">
+		SELECT
+			a.id,
+			a.screen_name AS screenName,
+			a.screen_code AS screenCode,
+			a.screen_url AS screenUrl,
+			a.screen_type AS screenType,
+			a.play_duration AS playDuration,
+			a.sort_order AS sortOrder,
+			a.is_enabled AS isEnabled,
+			a.remarks,
+			a.create_by AS createBy,
+			a.create_date AS createDate,
+			a.update_by AS updateBy,
+			a.update_date AS updateDate
+		FROM mes_screen_config a
+		WHERE a.is_enabled = #{isEnabled}
+		ORDER BY a.sort_order ASC
+	</select>
+
+</mapper>

+ 126 - 0
src/main/resources/views/modules/mes/mesScreenConfigForm.html

@@ -0,0 +1,126 @@
+<% layout('/layouts/default.html', {title: '大屏配置管理', libs: ['validate']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header with-border">
+			<div class="box-title">
+				<i class="fa icon-note"></i> ${text(mesScreenConfig.isNewRecord ? '新增大屏配置' : '编辑大屏配置')}
+			</div>
+			<div class="box-tools pull-right">
+				<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
+			</div>
+		</div>
+		<#form:form id="inputForm" model="${mesScreenConfig}" action="${ctx}/mes/mesScreenConfig/save" method="post" class="form-horizontal">
+			<div class="box-body">
+				<div class="form-unit">${text('基本信息')}</div>
+				<#form:hidden path="id"/>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('大屏名称')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="screenName" maxlength="100" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('大屏编码')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="screenCode" maxlength="50" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('大屏URL')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="screenUrl" maxlength="200" class="form-control required" placeholder="如: /js/a/mes/mesProduct/screen"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('大屏类型')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="screenType" maxlength="50" class="form-control required" placeholder="如: KPI数据、设备状态"/>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('轮播时长(秒)')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="playDuration" maxlength="5" class="form-control required digits" value="60"/>
+							</div>
+						</div>
+					</div>
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('排序')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:input path="sortOrder" maxlength="5" class="form-control required digits" value="0"/>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="row">
+					<div class="col-xs-6">
+						<div class="form-group">
+							<label class="control-label col-sm-4" title="">
+								<span class="required ">*</span> ${text('是否启用')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-8">
+								<#form:radio path="isEnabled" dictType="sys_yes_no" class="form-control required"/>
+							</div>
+						</div>
+					</div>
+				</div>
+				<div class="row">
+					<div class="col-xs-12">
+						<div class="form-group">
+							<label class="control-label col-sm-2" title="">
+								${text('备注')}:<i class="fa icon-question hide"></i></label>
+							<div class="col-sm-10">
+								<#form:textarea path="remarks" maxlength="500" class="form-control" rows="3"/>
+							</div>
+						</div>
+					</div>
+				</div>
+			</div>
+			<div class="box-footer">
+				<div class="row">
+					<div class="col-sm-offset-2 col-sm-10">
+						<% if (hasPermi('mes:mesScreenConfig:edit')){ %>
+							<button type="submit" class="btn btn-sm btn-primary" id="btnSubmit"><i class="fa fa-check"></i> ${text('保 存')}</button>&nbsp;
+						<% } %>
+						<button type="button" class="btn btn-sm btn-default" id="btnCancel" onclick="js.closeCurrentTabPage()"><i class="fa fa-reply-all"></i> ${text('关 闭')}</button>
+					</div>
+				</div>
+			</div>
+		</#form:form>
+	</div>
+</div>
+<% } %>
+<script>
+$("#inputForm").validate({
+	submitHandler: function(form){
+		js.ajaxSubmitForm($(form), function(data){
+			js.showMessage(data.message);
+			if(data.result == Global.TRUE){
+				js.closeCurrentTabPage(function(contentWindow){
+					contentWindow.page();
+				});
+			}
+		}, "json");
+    }
+});
+</script>

+ 78 - 0
src/main/resources/views/modules/mes/mesScreenConfigList.html

@@ -0,0 +1,78 @@
+<% layout('/layouts/default.html', {title: '大屏配置管理', libs: ['dataGrid']}){ %>
+<div class="main-content">
+	<div class="box box-main">
+		<div class="box-header">
+			<div class="box-title">
+				<i class="fa icon-notebook"></i> ${text('大屏配置管理')}
+			</div>
+			<div class="box-tools pull-right">
+				<a href="#" class="btn btn-default" id="btnSearch" title="${text('查询')}"><i class="fa fa-filter"></i> ${text('查询')}</a>
+				<a href="${ctx}/mes/mesScreenConfig/player" target="_blank" class="btn btn-default"><i class="fa fa-desktop"></i> ${text('大屏播放')}</a>
+				<% if(hasPermi('mes:mesScreenConfig:edit')){ %>
+					<a href="${ctx}/mes/mesScreenConfig/form" class="btn btn-default btnTool" title="${text('新增大屏配置')}"><i class="fa fa-plus"></i> ${text('新增')}</a>
+				<% } %>
+				<a href="#" class="btn btn-default" id="btnSetting" title="${text('设置')}"><i class="fa fa-navicon"></i></a>
+			</div>
+		</div>
+		<div class="box-body">
+			<#form:form id="searchForm" model="${mesScreenConfig}" action="${ctx}/mes/mesScreenConfig/listData" method="post" class="form-inline hide"
+					data-page-no="${parameter.pageNo}" data-page-size="${parameter.pageSize}" data-order-by="${parameter.orderBy}">
+				<div class="form-group">
+					<label class="control-label">${text('大屏名称')}:</label>
+					<div class="control-inline">
+						<#form:input path="screenName" maxlength="100" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('大屏编码')}:</label>
+					<div class="control-inline">
+						<#form:input path="screenCode" maxlength="50" class="form-control width-120"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<label class="control-label">${text('是否启用')}:</label>
+					<div class="control-inline">
+						<#form:select path="isEnabled" dictType="sys_yes_no" blankOption="true" class="form-control"/>
+					</div>
+				</div>
+				<div class="form-group">
+					<button type="submit" class="btn btn-primary btn-sm">${text('查询')}</button>
+					<button type="reset" class="btn btn-default btn-sm">${text('重置')}</button>
+				</div>
+			</#form:form>
+			<table id="dataGrid"></table>
+			<div id="dataGridPage"></div>
+		</div>
+	</div>
+</div>
+<% } %>
+<script>
+$('#dataGrid').dataGrid({
+	searchForm: $("#searchForm"),
+	columnModel: [
+		{header:'${text("大屏名称")}', name:'screenName', index:'a.screen_name', width:150, align:"center", frozen:true, formatter: function(val, obj, row, act){
+			return '<a href="${ctx}/mes/mesScreenConfig/form?id='+row.id+'" class="btnList" data-title="${text("编辑大屏配置")}">'+(val||row.id)+'</a>';
+		}},
+		{header:'${text("大屏编码")}', name:'screenCode', index:'a.screen_code', width:120, align:"center"},
+		{header:'${text("大屏URL")}', name:'screenUrl', index:'a.screen_url', width:200, align:"center"},
+		{header:'${text("大屏类型")}', name:'screenType', index:'a.screen_type', width:100, align:"center"},
+		{header:'${text("轮播时长(秒)")}', name:'playDuration', index:'a.play_duration', width:100, align:"center"},
+		{header:'${text("排序")}', name:'sortOrder', index:'a.sort_order', width:80, align:"center"},
+		{header:'${text("是否启用")}', name:'isEnabled', index:'a.is_enabled', width:80, align:"center", formatter: function(val, obj, row, act){
+			return val == '1' ? '是' : '否';
+		}},
+		{header:'${text("备注")}', name:'remarks', index:'a.remarks', width:150, align:"center"},
+		{header:'${text("操作")}', name:'actions', width:120, formatter: function(val, obj, row, act){
+			var actions = [];
+			<% if(hasPermi('mes:mesScreenConfig:edit')){ %>
+				actions.push('<a href="${ctx}/mes/mesScreenConfig/form?id='+row.id+'" class="btnList" title="${text("编辑大屏配置")}"><i class="fa fa-pencil"></i></a>&nbsp;');
+				actions.push('<a href="${ctx}/mes/mesScreenConfig/delete?id='+row.id+'" class="btnList" title="${text("删除大屏配置")}" data-confirm="${text("确认要删除该大屏配置吗?")}"><i class="fa fa-trash-o"></i></a>&nbsp;');
+			<% } %>
+			return actions.join('');
+		}}
+	],
+	frozenCols: true,
+	ajaxSuccess: function(data){
+	}
+});
+</script>

+ 311 - 0
src/main/resources/views/modules/mes/mesScreenPlayer.html

@@ -0,0 +1,311 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>MES大屏轮播播放器</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+        }
+        html, body {
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+            background: #000;
+        }
+        #player-container {
+            width: 100%;
+            height: 100%;
+            position: relative;
+            overflow: hidden;
+        }
+        #player-frame {
+            width: 100%;
+            height: 100%;
+            border: none;
+            display: block;
+            overflow: hidden;
+        }
+        #control-bar {
+            position: fixed;
+            top: 0;
+            right: 0;
+            height: 30px;
+            background: rgba(0, 0, 0, 0.6);
+            display: flex;
+            align-items: center;
+            padding: 0 15px;
+            z-index: 1000;
+            opacity: 0;
+            transition: opacity 0.3s;
+        }
+        #control-bar:hover {
+            opacity: 1;
+        }
+        #fullscreen-btn {
+            background: none;
+            border: none;
+            color: #fff;
+            cursor: pointer;
+            padding: 5px 10px;
+            font-size: 12px;
+        }
+        #fullscreen-btn:hover {
+            color: #1890ff;
+        }
+        #screen-info {
+            color: #fff;
+            font-size: 12px;
+        }
+        #screen-info span {
+            margin-right: 15px;
+        }
+        #progress-bar {
+            width: 100px;
+            height: 3px;
+            background: rgba(255,255,255,0.3);
+            margin: 0 10px;
+            cursor: pointer;
+            position: relative;
+        }
+        #progress-fill {
+            height: 100%;
+            background: #1890ff;
+            width: 0;
+            transition: width 1s linear;
+        }
+        #time-info {
+            color: #fff;
+            font-size: 12px;
+            min-width: 40px;
+            text-align: right;
+        }
+        .hidden {
+            display: none !important;
+        }
+        #loading {
+            position: fixed;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background: #000;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            z-index: 2000;
+        }
+        #loading .spinner {
+            width: 50px;
+            height: 50px;
+            border: 4px solid #333;
+            border-top: 4px solid #1890ff;
+            border-radius: 50%;
+            animation: spin 1s linear infinite;
+        }
+        @keyframes spin {
+            0% { transform: rotate(0deg); }
+            100% { transform: rotate(360deg); }
+        }
+        #loading-text {
+            color: #fff;
+            margin-top: 20px;
+            font-size: 16px;
+        }
+        #no-screen {
+            position: fixed;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background: #000;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            flex-direction: column;
+            z-index: 2000;
+        }
+        #no-screen h2 {
+            color: #ff4d4f;
+            font-size: 24px;
+            margin-bottom: 20px;
+        }
+        #no-screen p {
+            color: #999;
+            font-size: 16px;
+        }
+    </style>
+</head>
+<body>
+    <div id="loading">
+        <div style="text-align: center;">
+            <div class="spinner"></div>
+            <div id="loading-text">加载中...</div>
+        </div>
+    </div>
+
+    <div id="no-screen" class="hidden">
+        <h2>暂无大屏配置</h2>
+        <p>请先在管理页面配置需要轮播的大屏</p>
+    </div>
+
+    <div id="player-container">
+        <iframe id="player-frame" src=""></iframe>
+    </div>
+
+    <div id="control-bar" class="hidden">
+        <div id="screen-info">
+            <span id="current-screen-name"></span>
+            <span id="screen-count"></span>
+        </div>
+        <div id="progress-bar">
+            <div id="progress-fill"></div>
+        </div>
+        <div id="time-info">
+            <span id="countdown">60</span>s
+        </div>
+        <button id="fullscreen-btn" onclick="toggleFullScreen()">全屏</button>
+    </div>
+
+    <script src="https://cdn.jsdelivr.net/npm/jquery@1.11.3/dist/jquery.min.js"></script>
+    <script>
+        var screens = [];
+        var currentIndex = 0;
+        var currentDuration = 60;
+        var countdownTimer = null;
+        var progressTimer = null;
+        var remainingTime = 0;
+
+        var ctxPath = window.location.origin + '/js/a';
+
+        $(function() {
+            loadScreens();
+            document.addEventListener('keydown', function(e) {
+                if (e.key === 'ArrowLeft') {
+                    playScreen(currentIndex - 1);
+                } else if (e.key === 'ArrowRight') {
+                    playScreen(currentIndex + 1);
+                }
+            });
+        });
+
+        function loadScreens() {
+            var url = ctxPath + "/mes/mesScreenConfig/getScreenList";
+            $.get(url, function(res) {
+                if (res.result === "true" && res.data && res.data.length > 0) {
+                    screens = res.data;
+                    $('#loading').addClass('hidden');
+                    $('#control-bar').removeClass('hidden');
+                    playScreen(0);
+                } else {
+                    $('#loading').addClass('hidden');
+                    $('#no-screen').removeClass('hidden');
+                }
+            }).fail(function() {
+                $('#loading').addClass('hidden');
+                $('#no-screen').removeClass('hidden');
+            });
+        }
+
+        function playScreen(index) {
+            if (index < 0) {
+                index = screens.length - 1;
+            }
+            if (index >= screens.length) {
+                index = 0;
+            }
+            currentIndex = index;
+            var screen = screens[index];
+
+            currentDuration = screen.playDuration || 60;
+            remainingTime = currentDuration;
+
+            $('#current-screen-name').text(screen.screenName);
+            $('#screen-count').text((index + 1) + '/' + screens.length);
+            $('#countdown').text(remainingTime);
+            $('#progress-fill').css('width', '0%');
+
+            var screenUrl = screen.screenUrl;
+            if (screenUrl.startsWith('http')) {
+                // 绝对URL,直接使用
+            } else if (screenUrl.startsWith('/js/')) {
+                // 前端路由路径,已经包含 /js 前缀
+                screenUrl = window.location.origin + screenUrl;
+            } else if (!screenUrl.startsWith('/')) {
+                screenUrl = ctxPath + '/' + screenUrl;
+            }
+
+            $('#player-frame').attr('src', screenUrl);
+
+            startCountdown();
+        }
+
+        function startCountdown() {
+            clearInterval(countdownTimer);
+
+            $('#progress-fill').css('width', '0%');
+            $('#progress-fill').css('transition', 'none');
+
+            setTimeout(function() {
+                $('#progress-fill').css('transition', 'width ' + currentDuration + 's linear');
+                $('#progress-fill').css('width', '100%');
+            }, 100);
+
+            countdownTimer = setInterval(function() {
+                remainingTime--;
+                $('#countdown').text(remainingTime);
+
+                if (remainingTime <= 0) {
+                    clearInterval(countdownTimer);
+                    playScreen(currentIndex + 1);
+                }
+            }, 1000);
+        }
+
+        function changeScreen(index) {
+            playScreen(index);
+        }
+
+        function toggleFullScreen() {
+            if (!document.fullscreenElement) {
+                var elem = document.documentElement;
+                if (elem.requestFullscreen) {
+                    elem.requestFullscreen();
+                } else if (elem.webkitRequestFullscreen) {
+                    elem.webkitRequestFullscreen();
+                } else if (elem.msRequestFullscreen) {
+                    elem.msRequestFullscreen();
+                }
+                document.getElementById('fullscreen-btn').textContent = '退出全屏';
+            } else {
+                if (document.exitFullscreen) {
+                    document.exitFullscreen();
+                } else if (document.webkitExitFullscreen) {
+                    document.webkitExitFullscreen();
+                } else if (document.msExitFullscreen) {
+                    document.msExitFullscreen();
+                }
+                document.getElementById('fullscreen-btn').textContent = '全屏';
+            }
+        }
+
+        document.addEventListener('fullscreenchange', function() {
+            updateFullscreenBtn();
+        });
+        document.addEventListener('webkitfullscreenchange', function() {
+            updateFullscreenBtn();
+        });
+
+        function updateFullscreenBtn() {
+            if (document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement) {
+                document.getElementById('fullscreen-btn').textContent = '退出全屏';
+            } else {
+                document.getElementById('fullscreen-btn').textContent = '全屏';
+            }
+        }
+    </script>
+</body>
+</html>