channelDetailList.vue 42 KB

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