channelDetailList.vue 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  1. <style lang="scss" scoped>
  2. /deep/.vue-treeselect__control {
  3. line-height: 36px !important;
  4. }
  5. /deep/ .ant-collapse-item,
  6. /deep/.ant-collapse-content {
  7. overflow: inherit !important;
  8. }
  9. .search-bar {
  10. display: flex;
  11. align-items: center;
  12. }
  13. .search-box p {
  14. display: inline-block;
  15. border: 1px solid #f2f2f2;
  16. border-radius: 5px;
  17. margin-right: 10px;
  18. padding: 5px 10px;
  19. cursor: pointer;
  20. }
  21. </style>
  22. <style scoped>
  23. .showNumBox {
  24. margin: 10px 0;
  25. }
  26. .showNumBox .ant-card-body {
  27. display: flex;
  28. justify-content: center;
  29. }
  30. .showNumBox p,
  31. .showNumBox span {
  32. text-align: center;
  33. line-height: 40px;
  34. font-size: 30px;
  35. font-weight: 600;
  36. color: red;
  37. margin: 0;
  38. }
  39. .search-box .ant-card-body {
  40. padding: 5px 15px;
  41. }
  42. .showNumBox .ant-card-body .styleElse {
  43. line-height: 60px;
  44. height: 40px;
  45. font-size: 16px;
  46. font-weight: 400;
  47. margin-left: 10px;
  48. }
  49. .ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
  50. display: none !important;
  51. }
  52. .yincang .ant-col-6 p {
  53. text-align: left;
  54. color: red;
  55. font-size: 16px;
  56. font-weight: 500;
  57. }
  58. .ant-table-thead div {
  59. font-weight: 700;
  60. }
  61. .tool-tip {
  62. position: absolute;
  63. top: 65px;
  64. right: 10px;
  65. }
  66. </style>
  67. <style lang="less" scoped>
  68. .ant-card-head .ant-tabs-bar {
  69. padding: 0;
  70. }
  71. .search-box .ant-card-body {
  72. padding: 5px 15px;
  73. }
  74. .search-box {
  75. padding: 15px 10px;
  76. }
  77. .search-box p {
  78. display: inline-block;
  79. border: 1px solid #f2f2f2;
  80. border-radius: 5px;
  81. margin-right: 10px;
  82. padding: 5px 10px;
  83. cursor: pointer;
  84. }
  85. .statistics .ant-col-6 .ant-card-body .styleElse {
  86. line-height: 60px;
  87. height: 40px;
  88. font-size: 16px;
  89. font-weight: 400;
  90. margin-left: 10px;
  91. }
  92. .ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
  93. display: none !important;
  94. }
  95. .yincang .ant-col-6 p {
  96. text-align: left;
  97. color: red;
  98. font-size: 16px;
  99. font-weight: 500;
  100. }
  101. .ant-table-thead div {
  102. font-weight: 700;
  103. }
  104. .tool-tip {
  105. position: absolute;
  106. top: 65px;
  107. right: 10px;
  108. }
  109. .statistics {
  110. .ant-card-bordered {
  111. border: none;
  112. }
  113. .ant-card-head .ant-tabs {
  114. clear: both;
  115. margin-bottom: -13px;
  116. color: rgba(0, 0, 0, 0.65);
  117. font-weight: normal;
  118. font-size: 14px;
  119. }
  120. .duibi {
  121. position: absolute;
  122. right: 24px;
  123. top: 15px;
  124. }
  125. p {
  126. margin-bottom: 0;
  127. }
  128. }
  129. </style>
  130. <style lang="less" scoped>
  131. @import 'channelManage';
  132. </style>
  133. <template>
  134. <div class="channelManage config-project">
  135. <a-card>
  136. <div class="table-page-search-wrapper">
  137. <a-form layout="inline" :form="form" hide-required-mark :selfUpdate="true" @submit="handleQueryList">
  138. <a-row :gutter="24">
  139. <a-col :md="8" :sm="8" :xxl="6">
  140. <a-form-item label="渠道号名称">
  141. <a-input placeholder="请输入渠道号名称" v-decorator="['channelName']"></a-input>
  142. </a-form-item>
  143. </a-col>
  144. <a-col :md="8" :sm="8" :xxl="6">
  145. <a-form-item label="渠道号">
  146. <a-input placeholder="请输入渠道号" v-decorator="['channelCode']"></a-input>
  147. </a-form-item>
  148. </a-col>
  149. <a-col :md="8" :sm="8" :xxl="6">
  150. <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  151. <a-button type="primary" icon="search" @click="handleQueryList">查询</a-button>
  152. <a-button type="primary" @click="handleResetForm" icon="reload" class="middle-button"
  153. >重置</a-button
  154. >
  155. </span>
  156. </a-col>
  157. </a-row>
  158. </a-form>
  159. <a-row :gutter="24">
  160. <a-col :md="8" :sm="8" :xxl="6">
  161. <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
  162. <a-button type="primary" @click="visibleAddItem = true">添加单品</a-button>
  163. <a-button
  164. type="primary"
  165. @click="itemChannel"
  166. class="middle-button"
  167. :disabled="selectedRowKeys.length == 0"
  168. >关联单品</a-button
  169. >
  170. </span>
  171. </a-col>
  172. </a-row>
  173. </div>
  174. </a-card>
  175. <a-row style="margin-bottom:15px;margin-top:12px">
  176. <a-col :span="24">
  177. <div class="tableBody" style="min-height:200px;padding-bottom: 50px">
  178. <a-table
  179. :columns="columns"
  180. :dataSource="dataSource"
  181. :pagination="false"
  182. :loading="dataLoading"
  183. bordered
  184. @change="tableChange"
  185. size="middle"
  186. style="word-break: break-all;font-size:16px;font-weight:600"
  187. id="outTable"
  188. ref="accountTable"
  189. rowKey="id"
  190. :scroll="{ x: 3000 }"
  191. :rowSelection="{
  192. selectedRowKeys: selectedRowKeys,
  193. onChange: onSelectChange
  194. }"
  195. >
  196. <span slot="items" slot-scope="text, record">
  197. {{
  198. text.length > 0
  199. ? text
  200. .map(i => {
  201. return i.itemName
  202. })
  203. .join()
  204. : '-'
  205. }}
  206. </span>
  207. <span slot="state" slot-scope="text, record">
  208. <a-switch :checked="text === 1" @change="handleSwitchChang($event, record)" />
  209. </span>
  210. <span slot="action" slot-scope="text, records">
  211. <a @click="addNewChannel(records)" :disabled="!accountId">查看详情</a>
  212. </span>
  213. </a-table>
  214. <a-pagination
  215. size="small"
  216. :showTotal="ipagination.showTotal"
  217. style="float: right;margin-top:10px"
  218. v-if="dataSource.length > 0"
  219. showQuickJumper
  220. :pageSize.sync="ipagination.pageSize"
  221. :total="ipagination.total"
  222. v-model="ipagination.current"
  223. @change="getDataSource"
  224. />
  225. </div>
  226. </a-col>
  227. </a-row>
  228. <a-modal
  229. title="渠道号使用明细"
  230. :width="800"
  231. ref="modal"
  232. :visible="visibleChannel"
  233. :footer="null"
  234. @cancel="visibleChannel = false"
  235. >
  236. <a-table
  237. :columns="detailColumns"
  238. :dataSource="dataDetailSource"
  239. :pagination="ipaginationDetail"
  240. :loading="dataDetailLoading"
  241. bordered
  242. size="middle"
  243. style="word-break: break-all;font-size:16px;font-weight:600"
  244. id="outTable"
  245. ref="accountTable"
  246. rowKey="accountId"
  247. >
  248. </a-table>
  249. </a-modal>
  250. <a-modal
  251. title="关联单品"
  252. :width="800"
  253. ref="modal"
  254. :visible="visibleItem"
  255. @cancel="visibleItem = false"
  256. @ok="handleOkItem"
  257. >
  258. <a-form-model ref="itemForm" :model="itemForm" :rules="rules" v-bind="formItemLayout">
  259. <a-collapse accordion v-model="activeKey" ref="collapse">
  260. <template v-for="(item, index) in itemForm.items">
  261. <a-collapse-panel
  262. :forceRender="true"
  263. :header="item.channelName + '(' + item.channelCode + ')'"
  264. style="background: #f9f9fa;border-radius: 4px;margin-bottom:15px;overflow: hidden;border: 1px solid #d9d9d9;"
  265. >
  266. <span slot="extra">
  267. <a-popconfirm :title="`确定删除吗?`" @confirm="deleteRule($event, item, index)">
  268. <a-icon type="delete" @click="deleteIcon($event)" />
  269. </a-popconfirm>
  270. </span>
  271. <a-form-model-item label="产品" ref="projectId">
  272. <!-- <a-input v-model="item.projectId" placeholder="请输入规则名称" /> -->
  273. {{ item.productName }}
  274. </a-form-model-item>
  275. <a-form-model-item label="项目" ref="keyword">
  276. {{ item.projectName }}
  277. </a-form-model-item>
  278. <a-form-model-item label="渠道号" ref="channelCode">
  279. {{ item.channelCode }}
  280. </a-form-model-item>
  281. <a-form-model-item label="渠道号名称" ref="channelName">
  282. {{ item.channelName }}
  283. </a-form-model-item>
  284. <a-form-model-item
  285. label="关联单品名称"
  286. ref="projectId"
  287. :prop="'items.' + index + '.id'"
  288. :rules="[{ required: true, message: '请选择单品', trigger: 'blur' }]"
  289. >
  290. <a-select allowClear v-model="item.id">
  291. <a-select-option :value="item.id" v-for="(item, index) in item.itemList">{{
  292. item.itemName
  293. }}</a-select-option>
  294. </a-select>
  295. </a-form-model-item>
  296. </a-collapse-panel>
  297. </template>
  298. </a-collapse>
  299. </a-form-model>
  300. </a-modal>
  301. <a-modal
  302. title="添加单品"
  303. :width="800"
  304. ref="modal"
  305. :visible="visibleAddItem"
  306. @cancel="visibleAddItem = false"
  307. @ok="handleOk"
  308. :confirmLoading="confirmLoading"
  309. >
  310. <a-button type="primary" @click="addOneItem" style="margin-bottom:10px">添加单品信息</a-button>
  311. <a-form-model ref="ruleForm" :model="addItemForm" :rules="rules" v-bind="formItemLayout">
  312. <a-collapse accordion v-model="activeKey" ref="collapse">
  313. <template v-for="(item, index) in addItemForm.items">
  314. <a-collapse-panel
  315. :header="item.itemName"
  316. style="background: #f9f9fa;border-radius: 4px;margin-bottom:15px;overflow: hidden;border: 1px solid #d9d9d9;"
  317. >
  318. <span slot="extra">
  319. <a-popconfirm :title="`确定删除吗?`" @confirm="deleteRule($event, item, index)">
  320. <a-icon type="delete" @click="deleteIcon($event)" />
  321. </a-popconfirm>
  322. </span>
  323. <a-form-model-item
  324. label="项目"
  325. ref="projectId"
  326. :prop="'items.' + index + '.projectId'"
  327. :rules="[{ required: true, message: '请选择项目', trigger: 'blur' }]"
  328. >
  329. <!-- <a-input v-model="item.projectId" placeholder="请输入规则名称" /> -->
  330. <Treeselect v-model="item.projectId" style="width:100%" />
  331. </a-form-model-item>
  332. <a-form-model-item
  333. label="素材关键字"
  334. ref="keyword"
  335. :prop="'items.' + index + '.keyword'"
  336. :rules="[
  337. { required: true, message: '请填写素材关键字', trigger: 'blur' },
  338. { min: 1, message: '长度不得小于1', trigger: 'blur' }
  339. ]"
  340. >
  341. <a-input v-model="item.keyword" placeholder="请输入素材关键字" />
  342. </a-form-model-item>
  343. <a-form-model-item
  344. label="单品名称"
  345. ref="itemName"
  346. :prop="'items.' + index + '.itemName'"
  347. :rules="[
  348. { required: true, message: '请填写单品名称', trigger: 'blur' },
  349. { min: 1, message: '长度不得小于1', trigger: 'blur' }
  350. ]"
  351. >
  352. <a-input v-model="item.itemName" placeholder="请输入单品名称" />
  353. </a-form-model-item>
  354. </a-collapse-panel>
  355. </template>
  356. </a-collapse>
  357. </a-form-model>
  358. </a-modal>
  359. </div>
  360. </template>
  361. <script>
  362. import ARow from 'ant-design-vue/es/grid/Row'
  363. import ACol from 'ant-design-vue/es/grid/Col'
  364. import moment from 'moment'
  365. import { getKsAccountReport, getKsDetail, getReportList } from '@api/video.js'
  366. import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
  367. import selectTable from '@/views/modules/material/comment/selectTable.vue'
  368. import selectTableProject from '@/views/modules/Statistics/components/selectPagination.vue'
  369. import qs from 'qs'
  370. import Treeselect from './components/treeSelectProject.vue'
  371. let TTcolumns = [
  372. {
  373. title: '开关',
  374. dataIndex: 'state',
  375. scopedSlots: { customRender: 'state' },
  376. align: 'center',
  377. key: 'state'
  378. },
  379. {
  380. title: '生成方式(来源)',
  381. dataIndex: 'createType',
  382. align: 'center',
  383. key: 'createType',
  384. customRender: function(text) {
  385. if (text == 1) {
  386. return '系统生成'
  387. } else if (text == 2) {
  388. return '表格导入'
  389. } else if (text == 3) {
  390. return '自定义填写'
  391. } else {
  392. return text
  393. }
  394. }
  395. },
  396. {
  397. title: '创建时间',
  398. dataIndex: 'stateDate',
  399. scopedSlots: { customRender: 'stateDate' },
  400. align: 'center',
  401. key: 'stateDate'
  402. },
  403. {
  404. title: '渠道号',
  405. dataIndex: 'channelCode',
  406. scopedSlots: { customRender: 'channelCode' },
  407. align: 'center',
  408. key: 'channelCode'
  409. },
  410. {
  411. title: '渠道号名称',
  412. dataIndex: 'channelName',
  413. scopedSlots: { customRender: 'channelName' },
  414. align: 'center',
  415. key: 'channelName'
  416. },
  417. {
  418. title: '下载链接',
  419. dataIndex: 'url',
  420. scopedSlots: { customRender: 'url' },
  421. align: 'center',
  422. key: 'url',
  423. width: 300
  424. },
  425. {
  426. title: '调起链接',
  427. dataIndex: 'schemaUri',
  428. scopedSlots: { customRender: 'schemaUri' },
  429. align: 'center',
  430. key: 'schemaUri',
  431. width: 300
  432. },
  433. {
  434. title: '第三方点击监测链接',
  435. dataIndex: 'clickTrackUrl',
  436. scopedSlots: { customRender: 'clickTrackUrl' },
  437. align: 'center',
  438. key: 'clickTrackUrl',
  439. width: 300
  440. },
  441. {
  442. title: '第三方actionBar监测链接',
  443. dataIndex: 'actionbarClickUrl',
  444. scopedSlots: { customRender: 'actionbarClickUrl' },
  445. align: 'center',
  446. key: 'actionbarClickUrl',
  447. width: 300
  448. },
  449. {
  450. title: '是否关联单品',
  451. dataIndex: 'isHaveItem',
  452. customRender: function(text) {
  453. if (text == 1) {
  454. return '是'
  455. } else if (text == 0) {
  456. return '否'
  457. } else {
  458. return text
  459. }
  460. },
  461. align: 'center',
  462. key: 'isHaveItem'
  463. },
  464. {
  465. title: '关联单品名称',
  466. dataIndex: 'items',
  467. scopedSlots: { customRender: 'items' },
  468. align: 'center',
  469. key: 'items'
  470. },
  471. {
  472. title: '使用层级',
  473. dataIndex: 'usageLevel',
  474. customRender: function(text) {
  475. if (text == 'account') {
  476. return '账户'
  477. } else if (text == 'plan') {
  478. return '计划'
  479. } else if (text == 'group') {
  480. return '组'
  481. } else {
  482. return text
  483. }
  484. },
  485. align: 'center',
  486. key: 'usageLevel'
  487. },
  488. {
  489. title: '使用次数',
  490. dataIndex: 'usageTimes',
  491. scopedSlots: { customRender: 'usageTimes' },
  492. align: 'center',
  493. key: 'usageTimes'
  494. },
  495. {
  496. title: '是否循环',
  497. dataIndex: 'isCycle',
  498. customRender: function(text) {
  499. if (text == 1) {
  500. return '是'
  501. } else if (text == 0) {
  502. return '否'
  503. } else {
  504. return text
  505. }
  506. },
  507. align: 'center',
  508. key: 'isCycle'
  509. },
  510. {
  511. title: '循环次数',
  512. dataIndex: 'cycleTimes',
  513. scopedSlots: { customRender: 'cycleTimes' },
  514. align: 'center',
  515. key: 'cycleTimes'
  516. },
  517. {
  518. title: '当前已循环次数',
  519. dataIndex: 'haveCycleTimes',
  520. scopedSlots: { customRender: 'haveCycleTimes' },
  521. align: 'center',
  522. key: 'haveCycleTimes'
  523. },
  524. {
  525. title: '使用明细',
  526. dataIndex: 'action',
  527. scopedSlots: { customRender: 'action' },
  528. align: 'center',
  529. key: 'action'
  530. }
  531. ]
  532. let detailColumns = [
  533. {
  534. title: '渠道号',
  535. dataIndex: 'channelCode',
  536. scopedSlots: { customRender: 'channelCode' },
  537. align: 'center',
  538. key: 'channelCode'
  539. },
  540. {
  541. title: '使用范围',
  542. dataIndex: 'usageRange',
  543. customRender: function(text) {
  544. if (text == 1) {
  545. return '账户'
  546. } else if (text == 2) {
  547. return '项目'
  548. } else {
  549. return text
  550. }
  551. },
  552. align: 'center',
  553. key: 'usageRange'
  554. },
  555. {
  556. title: '项目名称',
  557. dataIndex: 'projectName',
  558. scopedSlots: { customRender: 'projectName' },
  559. align: 'center',
  560. key: 'projectName'
  561. },
  562. {
  563. title: '账户名称',
  564. dataIndex: 'authName',
  565. scopedSlots: { customRender: 'authName' },
  566. align: 'center',
  567. key: 'authName'
  568. },
  569. {
  570. title: '账户ID',
  571. dataIndex: 'accountId',
  572. scopedSlots: { customRender: 'accountId' },
  573. align: 'center',
  574. key: 'accountId'
  575. },
  576. {
  577. title: '创建广告计划ID',
  578. dataIndex: 'campaignId',
  579. scopedSlots: { customRender: 'campaignId' },
  580. align: 'center',
  581. key: 'campaignId'
  582. },
  583. {
  584. title: '创建广告组ID',
  585. dataIndex: 'unitId',
  586. scopedSlots: { customRender: 'unitId' },
  587. align: 'center',
  588. key: 'unitId'
  589. },
  590. {
  591. title: '创建时间',
  592. dataIndex: 'createTime',
  593. scopedSlots: { customRender: 'createTime' },
  594. align: 'center',
  595. key: 'createTime'
  596. }
  597. ]
  598. export default {
  599. components: {
  600. ACol,
  601. ARow,
  602. selectTable,
  603. selectTableProject
  604. },
  605. data() {
  606. return {
  607. productId: '',
  608. projectId: '',
  609. accountId: '',
  610. selectedRowKeys: [],
  611. visibleChannel: false,
  612. visibleAddItem: false,
  613. visibleItem: false,
  614. channelCode: '',
  615. channelType: 'a',
  616. createType: 1,
  617. indexAll: 0,
  618. spinning: false,
  619. form: this.$form.createForm(this),
  620. activeKey: '0',
  621. addItemForm: {
  622. items: [{ projectId: '', keyWord: '', itemName: '默认名称-单品1' }]
  623. },
  624. itemForm: {
  625. items: [{ project_Id: '', channelName: '', channelCode: '', projectName: '', productName: '' }]
  626. },
  627. confirmLoading: false,
  628. rules: {},
  629. formItemLayout: {
  630. labelCol: { span: 4 },
  631. wrapperCol: { span: 20 }
  632. },
  633. exportloading: false,
  634. dateRange: [moment().subtract(1, 'weeks'), moment()],
  635. noImg: require('@/assets/noImg.png'),
  636. validationRules: {
  637. bid: [
  638. {
  639. required: true,
  640. message: '出价信息必须填写'
  641. // validator: this.validateBid,
  642. }
  643. ]
  644. },
  645. ipagination: {
  646. current: 1,
  647. pageSize: 10,
  648. // pageSizeOptions: ['10', '20', '30'],
  649. showTotal: (total, range) => {
  650. return range[0] + '-' + range[1] + ' 共' + total + '条'
  651. },
  652. showQuickJumper: true,
  653. showSizeChanger: true,
  654. pageSizeOptions: ['10', '30', '50'],
  655. total: 0,
  656. onChange: (current, pageSize) => {
  657. // 切换分页时的回调,
  658. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  659. this.ipagination.current = current
  660. this.ipagination.pageSize = pageSize
  661. }
  662. },
  663. ipaginationDetail: {
  664. current: 1,
  665. pageSize: 10,
  666. // pageSizeOptions: ['10', '20', '30'],
  667. showTotal: (total, range) => {
  668. return range[0] + '-' + range[1] + ' 共' + total + '条'
  669. },
  670. showQuickJumper: true,
  671. total: 0,
  672. onChange: (current, pageSize) => {
  673. // 切换分页时的回调,
  674. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  675. this.ipaginationDetail.current = current
  676. this.ipaginationDetail.pageSize = pageSize
  677. this.dataDetailLoading = true
  678. var params = {}
  679. params.accountId = localStorage.getItem('channelInfoAccountId')
  680. ? localStorage.getItem('channelInfoAccountId')
  681. : null
  682. params.projectId = localStorage.getItem('channelInfoProjectId')
  683. ? localStorage.getItem('channelInfoProjectId')
  684. : null
  685. params.channelCode = this.channelCode
  686. params.pageNo = this.ipaginationDetail.current
  687. params.pageSize = this.ipaginationDetail.pageSize
  688. getAction('/channel/channelNumberUsageDetailsList', params).then(res => {
  689. this.dataDetailLoading = false
  690. if (res.success) {
  691. this.dataDetailSource = res.result.list || []
  692. this.ipaginationDetail.total = res.result.total || 0
  693. }
  694. })
  695. }
  696. },
  697. value: 'valid',
  698. KSaccountList: [],
  699. TTaccountList: [],
  700. KSdesignList: [],
  701. TTdesignList: [],
  702. operateDisabled: false,
  703. duration: 1000,
  704. //treeselect的参数
  705. treeValue: [],
  706. treeData: [],
  707. type: 3,
  708. operate: '',
  709. designList: [],
  710. tabKey: 1,
  711. loading: false,
  712. columns: [...TTcolumns],
  713. detailColumns: [...detailColumns],
  714. dataSource: [],
  715. dataDetailSource: [],
  716. dataDetailLoading: false,
  717. tableTab: 1,
  718. newPlan: 0,
  719. effectPlan: 0,
  720. openOptions: false,
  721. target: 'createTime',
  722. order: 'descend',
  723. dataLoading: false,
  724. url: '/channel/channelNumberDetails',
  725. modifyPriceVisible: false,
  726. modifyPriceLoading: false,
  727. modifyPriceDetail: null,
  728. accountVisible: false,
  729. againLoading: false,
  730. accountProjectDetail: null,
  731. accountProjectList: []
  732. }
  733. },
  734. components: {
  735. Treeselect
  736. },
  737. methods: {
  738. moment,
  739. deleteIcon(event) {
  740. event.stopPropagation()
  741. },
  742. deleteRule(event, item, index) {
  743. event.stopPropagation()
  744. this.addItemForm.items.splice(index, 1)
  745. },
  746. addOneItem() {
  747. this.addItemForm.items.push({
  748. projectId: '',
  749. keyWord: '',
  750. itemName: '默认名称-单品' + (this.addItemForm.items.length + 1)
  751. })
  752. },
  753. onSelectChange(selectedRowKeys, selectionRows) {
  754. this.selectedRowKeys = selectedRowKeys
  755. // this.selectionRows = selectionRows
  756. },
  757. handleSwitchChang(checked, data) {
  758. const paramsData = {
  759. id: data.id,
  760. state: checked ? 1 : 0
  761. }
  762. getAction('/channel/updateChannel', paramsData)
  763. .then(result => {
  764. if (result.code === 200) {
  765. const paramsData = this.form.getFieldsValue()
  766. this.handleGetTableList(paramsData)
  767. } else {
  768. this.$message.error(result.message)
  769. }
  770. })
  771. .catch(error => {
  772. console.log(error, 'eeee')
  773. })
  774. },
  775. cpaBidValid(rule, value, callback) {
  776. let z = /-/g
  777. let a = /\//g
  778. let d = /\./g
  779. if (value === '' || value === undefined) {
  780. callback('出价必须填写')
  781. } else if (value.startsWith('.') || value.endsWith('.')) {
  782. callback('请填写正确出价')
  783. } else if (value.startsWith('-') || value.endsWith('-')) {
  784. callback('请填写正确出价')
  785. } else if (value.match(a) && value.match(z)) {
  786. callback('不允许出现除"-"和"/"之外的所有字符,并且二者不可同时出现')
  787. } else if (value.match(/[^0-9+-\/]/g)) {
  788. callback('请填写正确出价')
  789. } else {
  790. callback()
  791. }
  792. },
  793. itemChannel() {
  794. postAction('/channel/channelNumberBindingItemInfo', { ids: this.selectedRowKeys }).then(res => {
  795. if (res.success) {
  796. this.itemForm.items = res.result.map((item, index) => {
  797. return {
  798. ...item,
  799. channelId: item.id,
  800. id: '',
  801. itemList: this.getItemList(item.project_Id, item.itemList, index)
  802. }
  803. })
  804. this.visibleItem = true
  805. }
  806. })
  807. },
  808. getItemList(projectId, list, index) {
  809. getAction('/channelItem/queryAllChannelItemByProjectId', { projectId }).then(res => {
  810. if (res.success) {
  811. this.itemForm.items[index].itemList = res.result
  812. }
  813. })
  814. },
  815. handleOkItem() {
  816. this.$refs.itemForm.validate(valid => {
  817. if (valid) {
  818. this.confirmLoading = true
  819. let params = this.itemForm.items.map(item => {
  820. return {
  821. id: item.id,
  822. channelId: item.channelId
  823. }
  824. })
  825. postAction('/channelItem/channelBindingItem', params).then(res => {
  826. this.confirmLoading = false
  827. if (res.success) {
  828. this.visibleItem = false
  829. this.itemForm.items = []
  830. this.handleResetForm()
  831. this.selectedRowKeys = []
  832. this.activeKey = '0'
  833. } else {
  834. this.$message.error(res.message)
  835. }
  836. })
  837. }
  838. })
  839. },
  840. handleOk() {
  841. this.$refs.ruleForm.validate(valid => {
  842. if (valid) {
  843. this.confirmLoading = true
  844. postAction('/channelItem/addChannelItem', this.addItemForm.items).then(res => {
  845. this.confirmLoading = false
  846. if (res.success) {
  847. this.visibleAddItem = false
  848. this.addItemForm.items = [{ projectId: '', keyWord: '', itemName: '默认名称-单品1' }]
  849. } else {
  850. this.$message.error(res.message)
  851. }
  852. })
  853. }
  854. })
  855. },
  856. handleCancel() {
  857. this.visibleChannel = false
  858. },
  859. addNewChannel(item) {
  860. this.visibleChannel = true
  861. this.dataDetailLoading = true
  862. this.channelCode = item.channelCode
  863. var params = {}
  864. params.accountId = localStorage.getItem('channelInfoAccountId')
  865. params.channelCode = item.channelCode
  866. params.pageNo = this.ipaginationDetail.current
  867. params.pageSize = this.ipaginationDetail.pageSize
  868. getAction('/channel/channelNumberUsageDetailsList', params).then(res => {
  869. this.dataDetailLoading = false
  870. if (res.success) {
  871. this.dataDetailSource = res.result.list || []
  872. this.ipaginationDetail.total = res.result.total || 0
  873. }
  874. })
  875. },
  876. getDataSource(current, pageSize) {
  877. // 切换分页时的回调,
  878. // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
  879. this.ipagination.current = current
  880. this.ipagination.pageSize = pageSize
  881. const paramsData = this.form.getFieldsValue()
  882. this.handleGetTableList(paramsData)
  883. },
  884. handleQueryList(event) {
  885. this.ipagination.current = 1
  886. event.preventDefault()
  887. const paramsData = this.form.getFieldsValue()
  888. this.handleGetTableList(paramsData)
  889. },
  890. handleResetForm() {
  891. this.ipagination.current = 1
  892. this.form.resetFields()
  893. const paramsData = this.form.getFieldsValue()
  894. this.handleGetTableList(paramsData)
  895. },
  896. handleGetTableList(data) {
  897. let paramsData = {
  898. channelCode: data.channelCode,
  899. channelName: data.channelName,
  900. accountId: localStorage.getItem('channelInfoAccountId')
  901. ? localStorage.getItem('channelInfoAccountId')
  902. : null,
  903. projectId: localStorage.getItem('channelInfoProjectId')
  904. ? localStorage.getItem('channelInfoProjectId')
  905. : null,
  906. pageNo: this.ipagination.current,
  907. pageSize: this.ipagination.pageSize
  908. }
  909. this.dataSource = []
  910. this.dataLoading = true
  911. this.getAction(this.url, paramsData)
  912. .then(result => {
  913. this.dataLoading = false
  914. if (result.code === 200) {
  915. this.dataSource = result.result.list || []
  916. this.ipagination.total = result.result.total || 0
  917. // result.result.total
  918. } else {
  919. this.$message.error(result.message)
  920. }
  921. })
  922. .catch(error => {
  923. this.dataLoading = false
  924. console.log(error, 'eeee')
  925. })
  926. },
  927. getAccountNoProject() {
  928. this.projectId = undefined
  929. const paramsData = this.form.getFieldsValue()
  930. this.handleGetTableList(paramsData)
  931. },
  932. disabledDate(current) {
  933. // Can not select days before today and today
  934. return current && current > moment().endOf('day')
  935. },
  936. dateChange(date, dateString) {
  937. // console.log(date,dateString)
  938. },
  939. filterOption(input, option) {
  940. // console.log(input, option)
  941. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  942. },
  943. operateChange(value) {
  944. console.log(value)
  945. if (value) {
  946. this.accountDisabled = true
  947. this.accountId = ''
  948. } else {
  949. this.accountDisabled = false
  950. }
  951. },
  952. tableChange(pagination, filters, sorter, { currentDataSource }) {
  953. this.ipagination.current = pagination.current
  954. this.ipagination.pageSize = pagination.pageSize
  955. if (sorter.order) {
  956. this.order = sorter.order ? sorter.order : 'descend'
  957. this.target = sorter.columnKey
  958. const paramsData = this.form.getFieldsValue()
  959. this.handleGetTableList({
  960. ...paramsData,
  961. target: sorter.columnKey,
  962. order: sorter.order ? sorter.order : 'descend'
  963. })
  964. }
  965. },
  966. // 获取所有运营
  967. getAllOperator(key) {
  968. let url = '/sys/user/getAllUserListV1'
  969. this.designList = []
  970. getAction(url, {}).then(res => {
  971. if (res.success) {
  972. this.designList = res.result
  973. }
  974. })
  975. }
  976. },
  977. watch: {
  978. productId: function(n, o) {
  979. if (n != '') {
  980. this.$refs.selectTableProject.keyValue = ''
  981. this.$refs.selectTableProject.getData(n)
  982. }
  983. }
  984. },
  985. computed: {
  986. newDate() {
  987. var myDate = new Date()
  988. myDate.getYear() //获取当前年份(2位)
  989. var n = myDate.getFullYear() //获取完整的年份(4位,1970-????)
  990. var m = myDate.getMonth() //获取当前月份(0-11,0代表1月)
  991. var d = myDate.getDate() //获取当前日(1-31)
  992. var day = myDate.getHours()
  993. return day
  994. }
  995. },
  996. mounted() {
  997. const paramsData = this.form.getFieldsValue()
  998. this.handleGetTableList(paramsData)
  999. if (localStorage.getItem('channelInfoAccountId')) {
  1000. this.accountId = localStorage.getItem('channelInfoAccountId')
  1001. } else {
  1002. this.accountId = null
  1003. }
  1004. this.getAllOperator()
  1005. },
  1006. activated: function() {},
  1007. filters: {
  1008. toPercentage(val) {
  1009. if (typeof val != 'string') {
  1010. return (val * 100).toFixed(2) + '%'
  1011. } else {
  1012. return val
  1013. }
  1014. },
  1015. //保留两位小数并且变成货币格式
  1016. decimalsHandle(val) {
  1017. if (val && typeof val != 'string') {
  1018. if (val >= 0) {
  1019. val = parseFloat(val).toFixed(2)
  1020. let numberStr = val.toString()
  1021. let str = numberStr.split('.')
  1022. let str0 = str[0].split('').reverse()
  1023. for (let i = 0; i < str0.length; i++) {
  1024. if ((i + 1) % 4 === 0) {
  1025. str0.splice(i, 0, ',')
  1026. }
  1027. }
  1028. str0.reverse()
  1029. let handleResult = ''
  1030. for (let j = 0; j < str0.length; j++) {
  1031. handleResult += str0[j]
  1032. }
  1033. return handleResult + '.' + str[1]
  1034. } else {
  1035. val = parseFloat(val).toFixed(2)
  1036. let numberStr = val.toString()
  1037. let str = numberStr.split('.')
  1038. let str0 = str[0]
  1039. .substr(1)
  1040. .split('')
  1041. .reverse()
  1042. for (let i = 0; i < str0.length; i++) {
  1043. if ((i + 1) % 4 === 0) {
  1044. str0.splice(i, 0, ',')
  1045. }
  1046. }
  1047. str0.reverse()
  1048. let handleResult = ''
  1049. for (let j = 0; j < str0.length; j++) {
  1050. handleResult += str0[j]
  1051. }
  1052. return '-' + handleResult + '.' + str[1]
  1053. }
  1054. } else if (typeof val == 'string') {
  1055. return val
  1056. } else {
  1057. return 0
  1058. }
  1059. },
  1060. //变成货币格式
  1061. formatCurrency(val) {
  1062. if (val) {
  1063. let numberStr = val.toString()
  1064. let str = numberStr.split('').reverse()
  1065. for (let i = 0; i < str.length; i++) {
  1066. if ((i + 1) % 4 === 0) {
  1067. str.splice(i, 0, ',')
  1068. }
  1069. }
  1070. str.reverse()
  1071. let handleResult = ''
  1072. for (let j = 0; j < str.length; j++) {
  1073. handleResult += str[j]
  1074. }
  1075. return handleResult
  1076. } else {
  1077. return '-'
  1078. }
  1079. }
  1080. }
  1081. }
  1082. </script>