index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <template>
  2. <!-- 一张图 -->
  3. <div style="height: 100%;">
  4. <div class="page-header"><el-input style="width: 260px;" placeholder="请输入大屏名称" prefix-icon="el-icon-search" clearable v-model="mapName"></el-input></div>
  5. <div class="content-list" v-infinite-scroll="searchMap" infinite-scroll-disabled="disabled" v-loading="loading">
  6. <el-row :gutter="20">
  7. <el-col :xs="12" :sm="8" :md="8" :lg="6" :xl="4" v-if="auth.includes('save')">
  8. <div class="li-item" @click="centerDialogVisible = true">
  9. <div class="add">
  10. <i class="el-icon-plus"></i>
  11. 新增大屏
  12. </div>
  13. </div>
  14. </el-col>
  15. <el-col :xs="12" :sm="8" :md="8" :lg="6" :xl="4" v-for="(li, index) in mapListData" :key="li.id">
  16. <div class="li-item">
  17. <div class="li-item-box">
  18. <div class="li-item-box-top">
  19. <el-image class="bg-img" :src="li.img | defaultImg" lazy></el-image>
  20. <div class="control-btn">
  21. <el-button round v-if="!!(li.state - 0)" size="mini" type="primary" @click="release(index)">预览</el-button>
  22. <el-button round v-if="auth.includes('publish') && !(li.state - 0)" size="mini" type="primary" @click="release(index)">发布</el-button>
  23. <el-button round v-if="auth.includes('update')" size="mini" type="warning" @click="edit(li)">编辑</el-button>
  24. <el-button round v-if="auth.includes('delete')" size="mini" type="danger" @click="delMap(li)">删除</el-button>
  25. </div>
  26. </div>
  27. <div class="li-item-box-bottom">
  28. <span>{{ li.mapName }}</span>
  29. <span>{{ li.state | state }}</span>
  30. </div>
  31. </div>
  32. </div>
  33. </el-col>
  34. </el-row>
  35. <!-- <p class="loading-text" v-if="loading">加载中...</p> -->
  36. <p class="loading-text" v-if="noMore">没有数据了</p>
  37. </div>
  38. <el-dialog title="新建大屏" :visible.sync="centerDialogVisible" width="400">
  39. <el-form ref="form" :model="form" label-width="80px" :hide-required-asterisk="true">
  40. <el-form-item label="大屏名称"><el-input v-model="form.mapName"></el-input></el-form-item>
  41. <el-form-item label="大屏描述"><el-input type="textarea" v-model="form.mapDesc"></el-input></el-form-item>
  42. <el-form-item label="套用框架">
  43. <el-select v-model="form.templateId" placeholder="请选择框架" style="width: 100%;">
  44. <el-option v-for="i in tplSelectData" :label="i.name" :value="i.id" :key="i.id"></el-option>
  45. </el-select>
  46. </el-form-item>
  47. </el-form>
  48. <span slot="footer">
  49. <el-button @click="centerDialogVisible = false">取 消</el-button>
  50. <el-button type="primary" @click="onSubmit">创 建</el-button>
  51. </span>
  52. </el-dialog>
  53. </div>
  54. </template>
  55. <script>
  56. export default {
  57. data() {
  58. return {
  59. //框架模板下拉
  60. tplSelectData: [],
  61. //新增大屏表单
  62. form: {
  63. mapName: '',
  64. templateId: '',
  65. mapDesc: ''
  66. },
  67. mapName: '',
  68. searchTimeFun: this.$timeFun(),
  69. //大屏列表
  70. listData: {
  71. total: -1 //默认值必须小于0
  72. },
  73. loading: false,
  74. centerDialogVisible: false,
  75. //当前选择大屏
  76. nowMapObj: {}
  77. };
  78. },
  79. filters: {
  80. state(value) {
  81. //0-未发布 1-已发布 2-撤回
  82. return value == 1 ? '已发布' : '未发布';
  83. },
  84. defaultImg(value) {
  85. return require('../../assets/images/map-defaut.jpg');
  86. }
  87. },
  88. computed: {
  89. //当前页权限
  90. auth() {
  91. const activePage = this.$route.path;
  92. return (
  93. this.$store.state.userTree
  94. .filter(x => {
  95. return x.url == activePage;
  96. })
  97. .map(x => {
  98. return x.auth;
  99. })[0] || []
  100. );
  101. },
  102. //大屏列表
  103. mapListData() {
  104. return (this.listData.list || []).map(x => {
  105. return {
  106. ...x,
  107. tplSrc: '/public/'
  108. };
  109. });
  110. },
  111. //是否加载
  112. noMore() {
  113. const { list = [], total = -1 } = this.listData;
  114. return !this.loading && total >= list.length;
  115. },
  116. //滚动条加载控制
  117. disabled() {
  118. return this.loading || this.noMore;
  119. },
  120. //计算大屏展示地址
  121. mapSrc() {
  122. const { tplSrc = '', id = '' } = this.nowMapObj;
  123. return `${tplSrc}?v=${Math.random(1,9999,0)}&id=${id}`;
  124. }
  125. },
  126. mounted() {
  127. this.$port.findMapTemplate().then(res => {
  128. this.tplSelectData = res.list;
  129. });
  130. },
  131. watch: {
  132. mapName(n) {
  133. this.searchMap(n);
  134. }
  135. },
  136. methods: {
  137. //搜索大屏
  138. searchMap(n) {
  139. this.loading = true;
  140. this.searchTimeFun(() => {
  141. this.$port
  142. .getMap({
  143. mapName: n || ''
  144. })
  145. .then(res => {
  146. this.listData = res;
  147. this.loading = false;
  148. });
  149. });
  150. },
  151. //新增提交
  152. onSubmit() {
  153. this.centerDialogVisible = false;
  154. this.$port.addMap(this.form).then(res => {
  155. this.searchMap();
  156. });
  157. },
  158. delMap(li) {
  159. this.$confirm('此操作将永久删除该大屏再也不能找回了, 是否继续?', '警告', {
  160. confirmButtonText: '确定',
  161. cancelButtonText: '取消',
  162. type: 'warning'
  163. })
  164. .then(() => {
  165. this.$port.delMap(li).then(res => {
  166. this.searchMap();
  167. this.$message({
  168. type: 'success',
  169. message: '删除成功!',
  170. duration:800
  171. });
  172. });
  173. })
  174. .catch(() => {
  175. this.$message({
  176. type: 'info',
  177. message: '已取消删除',
  178. duration:800
  179. });
  180. });
  181. },
  182. edit(e) {
  183. const { id = '', mapName = '', tplSrc = '' } = e;
  184. this.$router.push({
  185. path: '/a-picture/edit',
  186. query: {
  187. id,
  188. tplSrc
  189. }
  190. });
  191. },
  192. //发布
  193. release(index) {
  194. const e = (this.nowMapObj = this.mapListData[index]);
  195. //e.state == 1 预览 e.state == 0
  196. if (e.state == 1) {
  197. // window.open(this.mapSrc, '', 'channelmode=1,fullscreen=1,left=0,top=0,location=0');
  198. window.open(this.mapSrc);
  199. } else {
  200. this.$port.releaseMap(e).then(res => {
  201. if (!(res.code - 0)) {
  202. e.state = 1;
  203. this.listData.list.splice(index, 1, e);
  204. this.$alert(`发布成功:<a href=${this.mapSrc} target=_blank style="word-wrap:break-word;">去预览</a>`, '提示', {
  205. confirmButtonText: '关闭',
  206. dangerouslyUseHTMLString: true,
  207. type: 'success'
  208. });
  209. }
  210. });
  211. }
  212. }
  213. }
  214. };
  215. </script>
  216. <style lang="less" scoped>
  217. .page-header {
  218. display: flex;
  219. justify-content: flex-end;
  220. align-items: center;
  221. }
  222. .content-list {
  223. margin-top: 10px;
  224. .loading-text {
  225. font-size: 14px;
  226. display: block;
  227. text-align: center;
  228. }
  229. height: calc(100% - 98px);
  230. overflow: auto;
  231. padding: 0 2%;
  232. .li-item {
  233. display: flex;
  234. cursor: pointer;
  235. margin: 10px 0;
  236. zoom: 1; //清除浮动
  237. //清除浮动
  238. &::after {
  239. display: block;
  240. clear: both;
  241. content: '';
  242. visibility: hidden;
  243. height: 0;
  244. }
  245. //支撑高度
  246. &::before {
  247. content: '';
  248. float: left;
  249. width: 0;
  250. height: 0;
  251. padding-top: 60%; //控制高度
  252. overflow: hidden;
  253. opacity: 0;
  254. }
  255. //新增样式控制
  256. .add {
  257. flex: 1;
  258. display: flex;
  259. justify-content: center;
  260. align-items: center;
  261. color: #409eff;
  262. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  263. border-radius: 8px;
  264. border: 1px dashed;
  265. font-size: 1.2em;
  266. i {
  267. font-size: 1.2em;
  268. margin-right: 0.5rem;
  269. }
  270. &::before {
  271. padding-top: calc(60% - 2px);
  272. }
  273. }
  274. &-box {
  275. flex: 1;
  276. display: flex;
  277. flex-direction: column;
  278. overflow: hidden;
  279. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
  280. border-radius: 8px;
  281. &-top {
  282. position: relative;
  283. flex: 9;
  284. .bg-img,
  285. .control-btn {
  286. position: absolute;
  287. height: 100%;
  288. width: 100%;
  289. top: 0;
  290. bottom: 0;
  291. left: 0;
  292. right: 0;
  293. z-index: 0;
  294. }
  295. .control-btn {
  296. opacity: 0;
  297. transition: opacity 200ms;
  298. z-index: 1;
  299. background: rgba(255, 255, 255, 0.8);
  300. display: flex;
  301. flex-wrap: wrap;
  302. justify-content: center;
  303. align-items: center;
  304. &:hover {
  305. opacity: 1;
  306. }
  307. }
  308. }
  309. &-bottom {
  310. display: flex;
  311. justify-content: space-between;
  312. align-items: center;
  313. padding: 0 5%;
  314. flex: 3;
  315. }
  316. }
  317. }
  318. }
  319. </style>