plateDetail.vue 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. <template>
  2. <div class="mainBox">
  3. <div class="layerBox">
  4. <tableTitle :name="tableDivTitle" />
  5. <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="170px" class="demo-ruleForm">
  6. <div class="dialogText">
  7. <el-form-item label="通栏名称:" prop="sectorName">
  8. <el-input v-model="ruleForm.sectorName" placeholder="输入通栏名称"></el-input>
  9. </el-form-item>
  10. <el-form-item label="通栏编号:" prop="sectorId">
  11. <el-input v-model="ruleForm.sectorId" placeholder="输入通栏编号"></el-input>
  12. </el-form-item>
  13. <el-form-item label="画布高度:" prop="pic_height">
  14. <el-input v-model="ruleForm.pic_height" placeholder="输入画布高度"></el-input>
  15. </el-form-item>
  16. <el-form-item label="所属皮肤:" prop="templateStyle">
  17. <el-select v-model="ruleForm.templateStyle" placeholder="请选择所属皮肤">
  18. <el-option v-for="item in template_options" :key="item.template_id"
  19. :label="item.template_name" :value="item.template_id">
  20. </el-option>
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item label="皮肤id:" prop="templateStyle">
  24. <el-input v-model="ruleForm.templateStyle" placeholder="所属皮肤id" disabled></el-input>
  25. </el-form-item>
  26. <el-form-item label="通栏分类:" prop="sectorType">
  27. <el-select v-model="ruleForm.sectorType" placeholder="请选择通栏分类"
  28. :disabled="this.dialogName === '编辑'">
  29. <!-- 通栏分类:1:资讯类:2:通栏广告类;3:混合类;4:搜索框类;5:导航类;6:头条类;7:轮播图类; -->
  30. <el-option v-for="item in this.typeList" :label="item.label" :value="item.value"
  31. :key="item.value">{{ item.label }}</el-option>
  32. </el-select>
  33. </el-form-item>
  34. <el-form-item label="所属页面:" prop="pageType">
  35. <el-checkbox-group v-model="ruleForm.pageType" @change="changeCheckbox"
  36. :disabled="this.dialogName === '编辑'">
  37. <el-checkbox v-for="(item, index) in checkList" :key="index"
  38. :label="item.value">{{ item.label }}</el-checkbox>
  39. </el-checkbox-group>
  40. </el-form-item>
  41. <el-form-item label="通栏关键词:" class="custom-align-right">
  42. <template #label>
  43. <span class="askBox">
  44. 通栏关键词:
  45. <el-tooltip class="item" effect="dark" content="皮肤关键词,如:黑色、卡通、英雄。" placement="top">
  46. <i class="el-icon-question"></i>
  47. </el-tooltip>
  48. </span>
  49. </template>
  50. <tagInput :initialTags="tags" @tags-updated="updateTags"></tagInput>
  51. </el-form-item>
  52. <el-form-item label="通栏缩略图:" prop="image" :label-width="formLabelWidth"
  53. :class="['custom-form-item']" class="custom-align-right">
  54. <div class="uploaderBox">
  55. <!--图片上传组件 start ------------------------------------------------------------>
  56. <div class="avatar-upload-container" @mouseenter="hovering = true"
  57. @mouseleave="hovering = false">
  58. <!-- 上传组件 -->
  59. <el-upload class="avatar-uploader" action="#" :show-file-list="false"
  60. :before-upload="beforeAvatarUpload">
  61. <!-- 预览图片 -->
  62. <img v-if="this.logoUrl" :src="this.logoUrl" class="avatar">
  63. <!-- 上传图标 -->
  64. <div v-else class="chooseImgDiv">
  65. <div>
  66. <img src="@/assets/public/upload/noImage.png">
  67. <div>选择图片</div>
  68. </div>
  69. </div>
  70. <input type="hidden" name="logo" v-model="ruleForm.image">
  71. </el-upload>
  72. <!-- 删除按钮,当鼠标悬浮时显示 -->
  73. <div v-if="hovering && logoUrl" class="delete-button" @click="handleDelete">
  74. <i class="el-icon-delete"></i>
  75. </div>
  76. </div>
  77. <!--图片上传组件 end ------------------------------------------------------------>
  78. </div>
  79. </el-form-item>
  80. <el-form-item label="组件数量:" prop="component_num">
  81. <el-input v-model.number="ruleForm.component_num" id="component_num" placeholder="输入组件数量"
  82. type="number" min="1" @change="getPlaceList(ruleForm.component_num)">
  83. </el-input>
  84. </el-form-item>
  85. <el-form-item label="版式类型:" prop="sectorPlace">
  86. <el-select v-model="ruleForm.sectorPlace" placeholder="请选择版式类型" @change="changeStyleSort">
  87. <el-option v-for="item in sectorPlace_options" :key="item.sector_type"
  88. :label="item.name + '(' + item.width + '*' + item.height + ')'"
  89. :value="item.sector_type">{{ item.name + '(' + item.width + '*' + item.height + ')' }}
  90. </el-option>
  91. </el-select>
  92. </el-form-item>
  93. <el-form-item label="尺寸:" prop="sizeList" v-if="this.ruleForm.sectorPlace != ''">
  94. <p style="margin-top: 0px;">{{ ruleForm.sizeList }}</p>
  95. </el-form-item>
  96. <el-form-item label="通栏版式预览图:" prop="sector_img" v-if="this.ruleForm.sectorPlace != ''">
  97. <img :src="ruleForm.sector_img" alt="" width="300px" height="150px">
  98. </el-form-item>
  99. <div class="boxes-container" v-if="this.ruleForm.sizeList != '' && this.ruleForm.sectorPlace">
  100. <el-row class="layout-3">
  101. <el-row v-if="checkPlace" style="width: 100%;height: 100%;">
  102. <el-col v-for="(col, index) in JSON.parse(checkPlace.map)" :key="index"
  103. :style="{ width: col.col_data.col_width, height: '100%', marginRight: '1.2%' }">
  104. <el-row class="box" v-for="(row, rowIndex) in col.col_data.row_data" :key="rowIndex"
  105. :style="{
  106. height: row.row_height,
  107. width: (
  108. typeof row.row_width === 'string' && row.row_width.endsWith('%')
  109. ? (parseFloat(row.row_width) >= 100 ? row.row_width : '100%')
  110. : row.row_width
  111. ),
  112. marginBottom: '2.35%'
  113. }">
  114. {{component_option.find(item => item.sort_id == row.component_sort) ?
  115. `位置${component_option.find(item => item.sort_id == row.component_sort).sort_id}
  116. (${component_option.find(item => item.sort_id ==
  117. row.component_sort).width}*${component_option.find(item => item.sort_id ==
  118. row.component_sort).height})` : '' }}
  119. </el-row>
  120. </el-col>
  121. </el-row>
  122. </el-row>
  123. </div>
  124. <div v-for="(item, index) in component_option" :key="index" class="componentChoose">
  125. <el-form-item :label="item.name + ':'" :prop="`${index}`" class="componentOptions">
  126. <el-select v-model="ruleForm.component_code[index]" multiple clearable placeholder="请选择组件"
  127. class="componentOption_one">
  128. <el-option v-for="(compItem, comIndex) in item.component" :key="compItem.component_type"
  129. :label="compItem.component_name" :value="compItem.component_type">
  130. {{ compItem.component_name }}
  131. </el-option>
  132. </el-select>
  133. </el-form-item>
  134. </div>
  135. </div>
  136. <div class="dialogBtn">
  137. <el-button type="info" @click="cancelForm">取消</el-button>
  138. <el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
  139. </div>
  140. </el-form>
  141. </div>
  142. </div>
  143. </template>
  144. <script>
  145. //表格标题
  146. import tableTitle from './components/tableTitle.vue';
  147. import tagInput from '../../components/InputTag/index.vue';
  148. //引入公用样式
  149. import '@/styles/global.less';
  150. export default {
  151. components: {
  152. tableTitle,//表格标题-
  153. tagInput
  154. },
  155. data() {
  156. // 验证字符串或数组是否为空
  157. const validateEmpty = (rule, value, callback) => {
  158. if (typeof value === 'string' && value.trim() === '') {
  159. callback(new Error('该项不能为空!'))
  160. } else if (typeof value === 'number' && value === null) {
  161. // 数字类型不能调用 trim 方法,直接判断是否为 null
  162. callback(new Error('该项不能为空!'))
  163. } else {
  164. callback()
  165. }
  166. }
  167. // 验证数组是否为空
  168. const validateArray = (rule, value, callback) => {
  169. if (Array.isArray(value) && value.length === 0) {
  170. callback(new Error('该项不能为空!'))
  171. } else {
  172. callback()
  173. }
  174. }
  175. return {
  176. // 0.0画布及多选组件输入框相关----------start
  177. component: true, //验证组件是否有空数组
  178. name: '编辑', //备份dialogName来判断是否执行添加和编辑的异步
  179. tableData: [{}], // 添加空数据使表格正常显示
  180. // 初始化时设置默认值为 1,确保有初始布局
  181. component_num: 1,
  182. activeBoxes: [false], // 初始化激活状态数组
  183. selectedComponents: { 0: [] }, // 初始化组件选择对象
  184. // 0.0画布及多选组件输入框相关----------end
  185. //1.1 初始化信息
  186. tableDivTitle: "通栏列表", //列表标题
  187. dialogTableVisible: false, //编辑弹框
  188. dialogName: '编辑', //编辑弹窗名称
  189. plateLoading: true, //表格内容加载中
  190. tableData: [],//表格数据
  191. class_options: [],//风格下拉列表
  192. template_options: [],//皮肤下拉列表
  193. // componen_code: [],//组件版式及组件下拉列表
  194. sectorPlace_options: [],//通栏模版类型下拉列表
  195. component_option: [],
  196. tags: [],//标签数据
  197. templateStyle: '',//风格
  198. plateName: '',
  199. pageType: '',//页面类型
  200. value: '',
  201. checkList: [
  202. {
  203. value: 1,
  204. label: '首页',
  205. },
  206. {
  207. value: 2,
  208. label: '频道页',
  209. },
  210. {
  211. value: 3,
  212. label: '列表页',
  213. },
  214. {
  215. value: 4,
  216. label: '详情页',
  217. },
  218. {
  219. value: 5,
  220. label: '搜索页',
  221. },
  222. {
  223. value: 6,
  224. label: '单页(列表)',
  225. },
  226. {
  227. value: 7,
  228. label: '单页(详情)',
  229. },
  230. ],
  231. typeList: [],
  232. //活动id
  233. activeid: "",
  234. newArr: [],
  235. // 1.3 分页相关
  236. page: 1,
  237. pageSize: 10,
  238. total: 0,
  239. formLabelWidth: '', //广告示例图相关
  240. //1.4 弹框相关数据
  241. ruleForm: {
  242. sectorName: '',//通栏名称
  243. sectorPlace: null,//通栏模版类型
  244. component_num: null,//组件数量
  245. sectorId: '',//通栏编号id
  246. templateStyle: '',//所属皮肤
  247. pageType: '',//页面类型
  248. sizeList: '',//尺寸
  249. sectorType: null,//通栏类别
  250. pageType: [],//页面类型
  251. sectorKeyword: '',//通栏关键词
  252. image: '',//通栏展示图
  253. sector_img: '',//通栏版式预览图
  254. component_code: [],//所选择位置的组件
  255. sector_width: '',
  256. sector_height: '',
  257. pic_height: ''//画布高度
  258. },
  259. rules: {
  260. sectorName: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  261. component_num: [{ required: true, trigger: 'blur', message: '该项不能为空!' }],
  262. sectorId: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  263. templateStyle: [{ required: true, trigger: 'blur', validator: validateEmpty }],//关联皮肤名称
  264. sectorType: [{ required: true, trigger: 'blur', message: '该项不能为空!' }],
  265. image: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  266. sectorPlace: [{ required: true, trigger: 'blur', validator: validateEmpty }],
  267. component_code: [{ required: true, trigger: 'blur', validator: validateArray }],
  268. pageType: [{ required: true, trigger: 'blur', validator: validateArray }],
  269. pic_height: [{ required: true, trigger: 'blur', validator: validateEmpty }]
  270. },
  271. logoUrl: '',
  272. hovering: false, // 鼠标悬浮状态 悬浮时显示删除
  273. }
  274. },
  275. computed: {
  276. // 计算激活的方块索引
  277. activeBoxIndices() {
  278. return this.activeBoxes
  279. .map((active, index) => active ? index : null)
  280. .filter(index => index !== null);
  281. },
  282. checkPlace() {
  283. // 检查 sectorPlace_options 是否为数组,避免调用 find 方法时报错
  284. if (Array.isArray(this.sectorPlace_options)) {
  285. return this.sectorPlace_options.find(item => item.sector_type == this.ruleForm.sectorPlace);
  286. }
  287. return null;
  288. }
  289. },
  290. methods: {
  291. //1.列表和分页相关 start ------------------------------------------------------------>
  292. //1.1 开始请求列表信息方法
  293. // 获取版式列表
  294. getPlaceList(sectorType) {
  295. this.component_option = []
  296. this.ruleForm.component_code = []
  297. this.ruleForm.sectorPlace = ''
  298. let data = {
  299. component_num: this.ruleForm.component_num,
  300. type_id: 1,
  301. }
  302. this.$store.dispatch('plate/getAllSectorPlace', data).then(res => {
  303. this.sectorPlace_options = res.data
  304. }).catch(() => {
  305. this.$message({
  306. type: 'error',
  307. message: '网络错误,请重试!'
  308. });
  309. })
  310. // console.log("回显-22222",this.sectorPlace_options);
  311. },
  312. //获取风格列表
  313. getStyleList() {
  314. this.$store.dispatch('genre/getTemplateClass').then(res => {
  315. this.class_options = res.data
  316. // console.log(res.data);
  317. }).catch(() => {
  318. this.$message({
  319. type: 'error',
  320. message: '网络错误,请重试!'
  321. });
  322. })
  323. },
  324. //获取皮肤列表
  325. getSkinList() {
  326. let data = [];
  327. this.$store.dispatch('plate/getAllTemplate').then(res => {
  328. this.template_options = res.data
  329. console.log(res.data);
  330. }).catch(() => {
  331. this.$message({
  332. type: 'error',
  333. message: '网络错误,请重试!'
  334. });
  335. })
  336. },
  337. // 获取通栏分类
  338. getSectorType() {
  339. this.$store.dispatch('plate/getSectorType').then(res => {
  340. this.typeList = res.data
  341. this.typeList.forEach(item => {
  342. item.label = item.name
  343. item.value = item.id
  344. })
  345. console.log('获取类型', res.data);
  346. }).catch(() => {
  347. this.$message({
  348. type: 'error',
  349. message: '网络错误,请重试!'
  350. });
  351. })
  352. },
  353. //1.3 多选按钮发生变化
  354. changeCheckbox(val) {
  355. console.log(val)
  356. this.newArr = []
  357. val.forEach(item => {
  358. if (typeof item !== 'object' || !item.hasOwnProperty('__ob__')) {
  359. this.newArr.push(item)
  360. }
  361. });
  362. this.pageType = JSON.stringify(this.newArr)
  363. // console.log(this.pageType);
  364. },
  365. // 通栏版式发生变化
  366. changeStyleSort(val) {
  367. let num = 0;
  368. this.component_option = []
  369. this.activeBoxes = []
  370. this.selectedComponents = {}
  371. this.ruleForm.component_code = []
  372. if (this.sectorPlace_options && Array.isArray(this.sectorPlace_options)) {
  373. this.sectorPlace_options.forEach(item => {
  374. if (item.sector_type == val) {
  375. this.ruleForm.sizeList = item.width + ' * ' + item.height
  376. this.ruleForm.sector_img = item.sector_img
  377. this.ruleForm.size_id = item.size_id
  378. this.ruleForm.sector_width = item.width
  379. this.ruleForm.sector_height = item.height
  380. this.ruleForm.component_num = item.component_num;
  381. }
  382. })
  383. }
  384. let data = {
  385. sector_type: this.ruleForm.sectorPlace,
  386. type_id: 2,
  387. }
  388. this.$store.dispatch('plate/getAllSectorPlace', data).then(res => {
  389. this.component_option = res.data
  390. if (this.component_option && Array.isArray(this.component_option)) {
  391. this.component_option.forEach(item => {
  392. item.name = '位置' + item.sort_id + '(' + item.width + '*' + item.height + ')'
  393. })
  394. }
  395. }).catch(() => {
  396. this.$message({
  397. type: 'error',
  398. message: '网络错误,请重试!'
  399. });
  400. })
  401. },
  402. getStyleSort(val) {
  403. console.log('this.ruleForm.sectorPlace2222', this.ruleForm.sectorPlace);
  404. console.log('val', val);
  405. let data = {
  406. sector_type: this.ruleForm.sectorPlace,
  407. type_id: 2,
  408. }
  409. this.$store.dispatch('plate/getAllSectorPlace', data).then(res => {
  410. this.component_option = res.data
  411. this.component_option.forEach(item => {
  412. item.name = '位置' + item.sort_id + '(' + item.width + '*' + item.height + ')';
  413. })
  414. }).catch(() => {
  415. this.$message({
  416. type: 'error',
  417. message: '网络错误,请重试!'
  418. });
  419. })
  420. },
  421. //列表和分页相关 end ------------------------------------------------------------>
  422. //验证关联组件(每一个位置必须至少有一个组件)
  423. checkComponent() {
  424. this.component = true
  425. if (this.ruleForm.component_code && Array.isArray(this.ruleForm.component_code)) {
  426. const component = '';
  427. this.ruleForm.component_code.forEach(component => {
  428. if (component.length == 0) {
  429. this.component = false,
  430. console.log('component', component);
  431. this.$message({
  432. message: '请关联组件!',
  433. type: 'error'
  434. })
  435. }
  436. });
  437. // return this.component;
  438. }
  439. return true;
  440. },
  441. //1.9 编辑
  442. goEdit(id, val) {
  443. // console.log(id)
  444. let data = {
  445. id: this.$route.query.id
  446. };
  447. this.$store.dispatch('plate/getSectorInfo', data).then(res => {
  448. console.log('res回显', this.typeList)
  449. this.ruleForm.sectorName = res.data.sector_name//通栏名称
  450. this.ruleForm.sectorId = res.data.sector_id//通栏编号id
  451. this.ruleForm.templateStyle = res.data.template_id//关联皮肤名称
  452. this.ruleForm.component_num = res.data.component_num//组件数量
  453. this.ruleForm.sizeList = res.data.sector_width + ' * ' + res.data.sector_height//通栏尺寸
  454. this.ruleForm.sectorType = parseInt(res.data.sector_type)//通栏类别
  455. this.ruleForm.pageType = JSON.parse(res.data.page_type)// 通栏页面类型,根据符号|划分字符串为数组
  456. if(res.data.sector_keyword=='\"\"'){
  457. this.tags = []
  458. }else{
  459. this.tags = JSON.parse(res.data.sector_keyword)
  460. }
  461. this.ruleForm.plateCode = res.data.sector_code//通栏代码
  462. this.ruleForm.sectorKeyword = this.tags//通栏关键词
  463. this.ruleForm.image = res.data.sector_img//通栏展示图
  464. this.logoUrl = res.data.sector_img
  465. this.ruleForm.sector_img = res.data.place.sector_img
  466. this.sectorPlace_options = this.getPlaceList(res.data.component_num)
  467. this.ruleForm.sectorPlace = parseInt(res.data.place_type)
  468. this.getStyleSort(res.data.sectorPlace)
  469. // this.ruleForm.size_id = res.data.size_id;
  470. this.ruleForm.sector_width = res.data.sector_width
  471. this.ruleForm.sector_height = res.data.sector_height
  472. this.ruleForm.component_code = JSON.parse(res.data.component_code)
  473. this.ruleForm.pic_height = res.data.pic_height
  474. console.log('回显表单', this.ruleForm)
  475. console.log('回显表单', this.tags)
  476. }).catch(() => {
  477. this.$message({
  478. type: 'error',
  479. message: '网络错误,请重试!'
  480. });
  481. })
  482. },
  483. //1.7 添加
  484. addPlate() {
  485. this.dialogTableVisible = true
  486. this.dialogName = "添加"
  487. this.name = "添加"
  488. this.name = this.dialogName
  489. //添加时清空回显回来的数据
  490. this.ruleForm.sectorName = '' //通栏名称
  491. this.ruleForm.sectorId = '' //通栏编号id
  492. this.ruleForm.templateStyle = '' //关联皮肤名称
  493. this.ruleForm.sizeList = '' //通栏尺寸
  494. this.ruleForm.sectorType = null //通栏类别
  495. this.ruleForm.pageType = [] //通栏页面类型
  496. this.ruleForm.plateCode = '' //通栏代码
  497. this.ruleForm.sectorKeyword = '' //通栏关键词
  498. this.ruleForm.component_num = null //组件数量
  499. this.ruleForm.image = '' //通栏展示图
  500. this.ruleForm.sector_img = '' //通栏展示图
  501. // this.ruleForm.size_id = '' //通栏尺寸
  502. this.ruleForm.sectorPlace = '' //通栏版式编号
  503. this.logoUrl = ''
  504. this.ruleForm.image = ''
  505. this.tags = []
  506. this.ruleForm.component_code = []
  507. this.component_option = []
  508. this.ruleForm.sector_width = ''
  509. this.ruleForm.sector_height = ''
  510. // this.getPlaceList();
  511. this.selectedComponents = []
  512. this.activeBoxes = []
  513. },
  514. // 弹出层相关方法
  515. // 提交表单
  516. submitForm(formName) {
  517. console.log('this.ruleForm', this.dialogName)
  518. // this.name = this.dialogName
  519. console.log('this.ruleForm111', this.dialogName)
  520. console.log('this.ruleForm222', this.name)
  521. this.checkComponent()
  522. console.log('this.component', this.component)
  523. if (!this.component) {
  524. this.dialogName = ""
  525. return
  526. } else {
  527. this.dialogName = this.name
  528. }
  529. this.$refs[formName].validate((valid) => {
  530. if (valid) {
  531. if(this.ruleForm.sectorKeyword.length == 0){
  532. //如果没添加关键词,也就不需要验证了
  533. if (this.dialogName == "添加") {
  534. const data = {
  535. sector_name: this.ruleForm.sectorName, //通栏名称
  536. sector_id: this.ruleForm.sectorId, //通栏编号
  537. template_id: this.ruleForm.templateStyle, //所属皮肤
  538. // size_id: this.ruleForm.size_id, //通栏尺寸
  539. sector_type: this.ruleForm.sectorType, //通栏类别
  540. sector_code: this.ruleForm.plateCode, //通栏代码
  541. page_type: this.ruleForm.pageType, //页面类型
  542. component_num: this.ruleForm.component_num, //组件数量
  543. sector_keyword: JSON.stringify(this.ruleForm.sectorKeyword), //通栏关键词
  544. sector_img: this.logoUrl, //通栏展示图
  545. place_type: this.ruleForm.sectorPlace, //通栏版式id
  546. component_code: JSON.stringify(this.ruleForm.component_code), //通栏所选组件
  547. sector_width: this.ruleForm.sector_width, //通栏宽度
  548. sector_height: this.ruleForm.sector_height, //通栏高度
  549. pic_height: this.ruleForm.pic_height, //画布高度
  550. }
  551. console.log('添加表单--------data', data);
  552. this.$store.dispatch('plate/addSector', data).then(data => {
  553. if (data.code == 200) {
  554. this.$message({
  555. message: '添加成功',
  556. type: 'success'
  557. })
  558. this.$router.push({
  559. path: '/plate',
  560. });
  561. } else {
  562. this.$message({
  563. message: data.message,
  564. type: 'error'
  565. })
  566. }
  567. })
  568. }
  569. if (this.dialogName == "编辑") {
  570. const data = {
  571. id: this.$route.query.id,
  572. sector_name: this.ruleForm.sectorName, //通栏名称
  573. sector_id: this.ruleForm.sectorId, //通栏编号
  574. template_id: this.ruleForm.templateStyle, //所属皮肤
  575. // size_id: this.ruleForm.size_id, //通栏尺寸
  576. sector_type: this.ruleForm.sectorType, //通栏类别
  577. sector_code: this.ruleForm.plateCode, //通栏代码
  578. page_type: this.ruleForm.pageType, //页面类型
  579. component_num: this.ruleForm.component_num, //组件数量
  580. sector_keyword: JSON.stringify(this.ruleForm.sectorKeyword), //通栏关键词
  581. sector_img: this.ruleForm.image, //通栏展示图
  582. place_type: this.ruleForm.sectorPlace, //通栏版式id
  583. component_code: JSON.stringify(this.ruleForm.component_code), //通栏所选组件
  584. sector_width: this.ruleForm.sector_width, //通栏宽度
  585. sector_height: this.ruleForm.sector_height, //通栏高度
  586. pic_height: this.ruleForm.pic_height, //画布高度
  587. }
  588. console.log('编辑表单---data', data);
  589. this.$store.dispatch('plate/updateSector', data).then(data => {
  590. if (data.code == 200) {
  591. this.$message({
  592. message: '编辑成功',
  593. type: 'success'
  594. })
  595. this.$router.push({
  596. path: '/plate',
  597. });
  598. } else {
  599. this.$message({
  600. message: data.message,
  601. type: 'error'
  602. })
  603. }
  604. })
  605. }
  606. }else{
  607. //验证关键词是否重复 start ------------------------------------------------------------>
  608. let StringKeyword;
  609. if(this.ruleForm.sectorKeyword.length == 1){
  610. let ar = [];
  611. ar.push(this.ruleForm.sectorKeyword[0]);
  612. StringKeyword = JSON.stringify(ar);
  613. }else{
  614. StringKeyword = JSON.stringify(this.ruleForm.sectorKeyword);
  615. }
  616. let data = {
  617. keyword: StringKeyword,
  618. type : 'sector',
  619. template_id:this.ruleForm.templateStyle,
  620. id:this.$route.query.id
  621. }
  622. this.$store.dispatch('genre/checkRepeatKeyword', data).then(res => {
  623. if (res.code == 200) {
  624. if (this.dialogName == "添加") {
  625. const data = {
  626. sector_name: this.ruleForm.sectorName, //通栏名称
  627. sector_id: this.ruleForm.sectorId, //通栏编号
  628. template_id: this.ruleForm.templateStyle, //所属皮肤
  629. // size_id: this.ruleForm.size_id, //通栏尺寸
  630. sector_type: this.ruleForm.sectorType, //通栏类别
  631. sector_code: this.ruleForm.plateCode, //通栏代码
  632. page_type: this.ruleForm.pageType, //页面类型
  633. component_num: this.ruleForm.component_num, //组件数量
  634. sector_keyword: JSON.stringify(this.ruleForm.sectorKeyword), //通栏关键词
  635. sector_img: this.logoUrl, //通栏展示图
  636. place_type: this.ruleForm.sectorPlace, //通栏版式id
  637. component_code: JSON.stringify(this.ruleForm.component_code), //通栏所选组件
  638. sector_width: this.ruleForm.sector_width, //通栏宽度
  639. sector_height: this.ruleForm.sector_height, //通栏高度
  640. pic_height: this.ruleForm.pic_height, //画布高度
  641. }
  642. console.log('添加表单--------data', data);
  643. this.$store.dispatch('plate/addSector', data).then(data => {
  644. if (data.code == 200) {
  645. this.$message({
  646. message: '添加成功',
  647. type: 'success'
  648. })
  649. this.$router.push({
  650. path: '/plate',
  651. });
  652. } else {
  653. this.$message({
  654. message: data.message,
  655. type: 'error'
  656. })
  657. }
  658. })
  659. }
  660. if (this.dialogName == "编辑") {
  661. const data = {
  662. id: this.$route.query.id,
  663. sector_name: this.ruleForm.sectorName, //通栏名称
  664. sector_id: this.ruleForm.sectorId, //通栏编号
  665. template_id: this.ruleForm.templateStyle, //所属皮肤
  666. // size_id: this.ruleForm.size_id, //通栏尺寸
  667. sector_type: this.ruleForm.sectorType, //通栏类别
  668. sector_code: this.ruleForm.plateCode, //通栏代码
  669. page_type: this.ruleForm.pageType, //页面类型
  670. component_num: this.ruleForm.component_num, //组件数量
  671. sector_keyword: JSON.stringify(this.ruleForm.sectorKeyword), //通栏关键词
  672. sector_img: this.ruleForm.image, //通栏展示图
  673. place_type: this.ruleForm.sectorPlace, //通栏版式id
  674. component_code: JSON.stringify(this.ruleForm.component_code), //通栏所选组件
  675. sector_width: this.ruleForm.sector_width, //通栏宽度
  676. sector_height: this.ruleForm.sector_height, //通栏高度
  677. pic_height: this.ruleForm.pic_height, //画布高度
  678. }
  679. console.log('编辑表单---data', data);
  680. this.$store.dispatch('plate/updateSector', data).then(data => {
  681. if (data.code == 200) {
  682. this.$message({
  683. message: '编辑成功',
  684. type: 'success'
  685. })
  686. this.$router.push({
  687. path: '/plate',
  688. });
  689. } else {
  690. this.$message({
  691. message: data.message,
  692. type: 'error'
  693. })
  694. }
  695. })
  696. }
  697. } else {
  698. this.$message.error(res.message);
  699. }
  700. })
  701. //验证关键词是否重复 end ------------------------------------------------------------>
  702. }
  703. } else {
  704. console.log(this.$refs[formName]);
  705. return;
  706. }
  707. });
  708. },
  709. //取消添加或编辑
  710. cancelForm() {
  711. this.$router.push({
  712. path: '/plate',
  713. });
  714. },
  715. // 验证输入的数量
  716. validateCount() {
  717. // 确保是数字且在1-3范围内(因为输入框min为1,移除小于0的判断)
  718. let count = parseInt(this.component_num, 10);
  719. if (isNaN(count)) count = 1;
  720. if (count > 3) count = 3;
  721. this.component_num = count;
  722. // 初始化激活状态数组
  723. this.activeBoxes = Array(count).fill(false);
  724. // 初始化组件选择对象
  725. this.selectedComponents = {};
  726. for (let i = 0; i < count; i++) {
  727. this.selectedComponents[i] = [];
  728. }
  729. },
  730. // 切换方块激活状态
  731. toggleBox(index) {
  732. this.$set(this.activeBoxes, index, this.component_option[index])
  733. },
  734. //3.6 上传图片操作
  735. beforeAvatarUpload(file) {
  736. const isJPG = file.type === 'image/jpeg';
  737. const isPNG = file.type === 'image/png';
  738. const isLt2M = file.size / 1024 / 1024 < 2;
  739. if (!isJPG && !isPNG) {
  740. this.$message.error('上传图片只能是 JPG 或 PNG 格式!');
  741. return false;
  742. }
  743. if (!isLt2M) {
  744. this.$message.error('上传图片大小不能超过 2MB!');
  745. return false;
  746. }
  747. const formData = new FormData();
  748. formData.append('file', file);
  749. this.$store.dispatch('pool/uploadFile', formData).then(res => {
  750. this.logoUrl = res.data.imgUrl;//显示缩略图
  751. this.ruleForm.image = res.data.imgUrl;//提供表单地址
  752. console.log(res.data.imgUrl)
  753. }).catch(() => {
  754. this.$message({
  755. type: 'info',
  756. message: '网络错误,请重试!'
  757. });
  758. })
  759. // 阻止默认的上传行为
  760. return false;
  761. },
  762. handleDelete() {
  763. // 删除图片
  764. this.logoUrl = ''; // 清空图片 URL
  765. },
  766. // 关键词标签
  767. updateTags(newTags) {
  768. this.tags = newTags;
  769. this.ruleForm.sectorKeyword = newTags;
  770. },
  771. },
  772. mounted() {
  773. if (this.$route.query.id && this.$route.query.id != 0) {
  774. this.dialogName = '编辑',
  775. this.goEdit()
  776. } else {
  777. this.dialogName = '添加',
  778. this.addPlate()
  779. }
  780. this.getStyleList()
  781. this.getSkinList()
  782. this.getSectorType()
  783. },
  784. watch: {
  785. component_num(newVal) {
  786. this.validateCount();
  787. },
  788. 'ruleForm.component_num': {
  789. handler(oldVal, newVal) {
  790. console.log('监听val', oldVal);
  791. console.log('监听newval', newVal);
  792. if (!(this.newVal !== null && this.dialogName == '编辑')) {
  793. this.component_option = [];
  794. this.ruleForm.component_code = [];
  795. this.ruleForm.sectorPlace = '';
  796. }
  797. },
  798. deep: true
  799. }
  800. }
  801. }
  802. </script>
  803. <style scoped lang="less">
  804. input[aria-hidden=true] {
  805. display: none !important;
  806. }
  807. .tips {
  808. margin: 30px;
  809. background-color: #e9ecf9;
  810. border-radius: 11px;
  811. .tipsIcon {
  812. margin: 10px 15px;
  813. display: inline-block;
  814. width: 24px;
  815. height: 24px;
  816. background: url("../../assets/advertise/Info Circle.png") no-repeat;
  817. vertical-align: middle;
  818. }
  819. .tipsText {
  820. font-size: 14px;
  821. color: #666666;
  822. }
  823. }
  824. .title {
  825. margin: 30px 30px 20px 30px;
  826. padding: 30px 30px 40px 30px;
  827. background-color: #fff;
  828. border-radius: 20px 20px 20px 20px;
  829. border: 1px solid #E9EDF7;
  830. .left {
  831. float: left;
  832. }
  833. .right {
  834. float: right;
  835. }
  836. .searchBox {
  837. ::v-deep .el-input {
  838. position: relative;
  839. font-size: 14px;
  840. display: inline-block;
  841. width: 80%;
  842. }
  843. .searchTitle {
  844. padding-bottom: 10px;
  845. font-family: Microsoft YaHei, Microsoft YaHei;
  846. font-weight: 400;
  847. font-size: 14px;
  848. color: #999999;
  849. line-height: 16px;
  850. }
  851. .el-select {
  852. width: 100%;
  853. display: inline-block;
  854. position: relative;
  855. }
  856. }
  857. .btnList {
  858. float: right;
  859. padding-top: 28px;
  860. button {
  861. height: 38px;
  862. border: none;
  863. border-radius: 8px;
  864. padding: 0 30px;
  865. }
  866. .search {
  867. background-color: #5570f1;
  868. color: #fff;
  869. margin-right: 20px;
  870. }
  871. .reset {
  872. font-family: Microsoft YaHei, Microsoft YaHei;
  873. font-weight: 400;
  874. font-size: 16px;
  875. color: #333333;
  876. background: #F5F7FB;
  877. border-radius: 8px 8px 8px 8px;
  878. border: 1px solid rgba(85, 112, 241, 0.11);
  879. }
  880. }
  881. }
  882. .layerBox {
  883. padding: 30px 20px;
  884. position: relative;
  885. .btn {
  886. position: absolute;
  887. top: 30px;
  888. right: 20px;
  889. height: 38px;
  890. color: #fff;
  891. background-color: #5570f1;
  892. border: none;
  893. border-radius: 8px;
  894. padding: 8px 28px 9px;
  895. box-sizing: border-box;
  896. }
  897. .listBtnBox {
  898. justify-content: left;
  899. }
  900. .listDeleteBtn,
  901. .listEditBtn {
  902. margin-left: 0px;
  903. padding-left: 0px;
  904. margin-right: 20px;
  905. width: 76px;
  906. height: 36px;
  907. line-height: 36px;
  908. }
  909. ::v-deep .el-form-item {
  910. margin-bottom: 50px;
  911. }
  912. ::v-deep .el-select {
  913. width: 100%;
  914. }
  915. ::v-deep .el-input--medium,
  916. ::v-deep .el-form-item__label {
  917. line-height: 36px;
  918. font-size: 14px;
  919. }
  920. }
  921. .boxes-container {
  922. margin-left: 170px;
  923. width: 700px;
  924. height: 350px;
  925. margin-bottom: 25px;
  926. border: 1px dashed #d1d5db;
  927. border-radius: 6px;
  928. overflow: hidden;
  929. }
  930. .box {
  931. display: flex;
  932. align-items: center;
  933. justify-content: center;
  934. color: white;
  935. font-weight: 600;
  936. cursor: pointer;
  937. transition: all 0.2s ease;
  938. }
  939. .box:hover {
  940. filter: brightness(1.1);
  941. }
  942. .box.active {
  943. background-color: #1e40af;
  944. box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  945. }
  946. .layout-3 {
  947. display: flex;
  948. height: 100%;
  949. /* 固定高度确保左右等高 */
  950. gap: 10px;
  951. padding: 10px;
  952. }
  953. .layout-3-left {
  954. flex: 1.5;
  955. display: flex;
  956. flex-direction: column;
  957. gap: 10px;
  958. height: 100%;
  959. }
  960. .layout-3-right {
  961. flex: 1;
  962. height: 100%;
  963. }
  964. .layout-3-left .box {
  965. height: 50%;
  966. }
  967. .layout-3 .box {
  968. background-color: #3b82f6;
  969. border-radius: 6px;
  970. height: 100%;
  971. }
  972. .layout-3-1 .box {
  973. background-color: #3b82f6;
  974. border-radius: 6px;
  975. height: 100%;
  976. }
  977. .layout-3-1-left {
  978. flex: 3;
  979. height: 100%;
  980. }
  981. .layout-3-1-right {
  982. flex: 1;
  983. display: flex;
  984. flex-direction: column;
  985. gap: 10px;
  986. height: 100%;
  987. }
  988. .layout-3-1-right .box {
  989. height: 50%;
  990. }
  991. .layout-3-1-left .box {
  992. height: 100%;
  993. }
  994. .layout-3-1 {
  995. display: flex;
  996. height: 100%;
  997. gap: 10px;
  998. padding: 10px;
  999. }
  1000. .layout-2 {
  1001. display: flex;
  1002. height: 100%;
  1003. gap: 10px;
  1004. padding: 10px;
  1005. }
  1006. .layout-2-left {
  1007. flex: 5;
  1008. height: 100%;
  1009. }
  1010. .layout-2-right {
  1011. flex: 5;
  1012. height: 100%;
  1013. }
  1014. .layout-2 .box {
  1015. background-color: #3b82f6;
  1016. border-radius: 6px;
  1017. height: 100%;
  1018. width: 100%;
  1019. }
  1020. /* 数量=1的布局 */
  1021. .layout-1 {
  1022. height: 100%;
  1023. padding: 10px;
  1024. }
  1025. .layout-1 .box {
  1026. background-color: #3b82f6;
  1027. border-radius: 6px;
  1028. height: 100%;
  1029. width: 100%;
  1030. }
  1031. /* 输入框区域样式 */
  1032. .input-fields {
  1033. display: flex;
  1034. flex-direction: column;
  1035. gap: 15px;
  1036. margin-top: 20px;
  1037. }
  1038. .field-item {
  1039. display: flex;
  1040. align-items: center;
  1041. gap: 15px;
  1042. padding: 12px;
  1043. background-color: #f9fafb;
  1044. border-radius: 6px;
  1045. }
  1046. .field-label {
  1047. width: 120px;
  1048. font-weight: 600;
  1049. color: #374151;
  1050. }
  1051. .size-select {
  1052. flex: 1;
  1053. padding: 8px;
  1054. border: 1px solid #d1d5db;
  1055. border-radius: 4px;
  1056. height: 100px;
  1057. background-color: white;
  1058. }
  1059. .size-select option {
  1060. padding: 4px 0;
  1061. }
  1062. // 弹出层内容
  1063. .dialogText {
  1064. margin: 0 7px 0 3px;
  1065. padding-bottom: 1px;
  1066. padding: 30px 60px 1px 20px;
  1067. background-color: #f5f7fb;
  1068. .adImage {
  1069. width: 140px;
  1070. height: 140px;
  1071. line-height: 210px;
  1072. border-radius: 12px;
  1073. border: 1px solid rgba(85, 112, 241, 0.11);
  1074. img {
  1075. width: 140px;
  1076. height: 80px;
  1077. }
  1078. }
  1079. ::v-deep .avatar {
  1080. width: 140px;
  1081. height: auto;
  1082. }
  1083. .price {
  1084. ::v-deep .el-input {
  1085. width: 29%;
  1086. }
  1087. }
  1088. .example {
  1089. font-family: Microsoft YaHei;
  1090. color: #5570F1;
  1091. }
  1092. .el_btnList {
  1093. margin-right: 15px;
  1094. margin-top: 20px;
  1095. }
  1096. ::v-deep .el-date-editor.el-input {
  1097. width: 48%;
  1098. }
  1099. ::v-deep .el-button+.el-button {
  1100. margin-left: 0px;
  1101. }
  1102. ::v-deep .el-select {
  1103. width: 100%;
  1104. }
  1105. ::v-deep .el-form-item {
  1106. margin-bottom: 20px;
  1107. }
  1108. }
  1109. .dialogBtn {
  1110. text-align: center;
  1111. margin: 30px auto 20px;
  1112. clear: both;
  1113. button {
  1114. width: 184px;
  1115. padding: 16px;
  1116. font-family: Microsoft YaHei, Microsoft YaHei;
  1117. font-weight: 400;
  1118. font-size: 20px;
  1119. border: none;
  1120. border-radius: 12px 12px 12px 12px;
  1121. }
  1122. .cancel {
  1123. color: #333333;
  1124. background-color: #f5f7fb;
  1125. border: 2px solid rgba(85, 112, 241, 0.11);
  1126. }
  1127. .submit {
  1128. color: #fff;
  1129. background-color: #5570F1;
  1130. margin-left: 40px;
  1131. }
  1132. }
  1133. .radioGroup {
  1134. ::v-deep .el-form-item {
  1135. margin-top: 40px;
  1136. margin-bottom: 0;
  1137. }
  1138. }
  1139. .graph {
  1140. background-color: #f5f7fb;
  1141. padding: 60px 100px;
  1142. overflow: hidden;
  1143. li {
  1144. float: left;
  1145. }
  1146. >li:first-child {
  1147. margin-right: 100px;
  1148. }
  1149. }
  1150. .dialog-footer {
  1151. margin: 0 auto;
  1152. }
  1153. .rowMargin {
  1154. margin-top: 20px;
  1155. }
  1156. .componentChoose {
  1157. background-color: #f5f7fb;
  1158. overflow: hidden;
  1159. }
  1160. .componentOptions {
  1161. float: left;
  1162. margin-right: 30px;
  1163. width: 100%;
  1164. }
  1165. .componentOption_one {
  1166. width: 100%;
  1167. }
  1168. </style>