direction-exclusion.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <template>
  2. <div class="direction-exclusion">
  3. <a-input-search
  4. v-model:value="search"
  5. :placeholder="
  6. type === 'crowd' ? '请输入人群包名称或ID' : '请输入媒体包名称或ID'
  7. "
  8. style="width: 200px"
  9. @input="onSearch"
  10. />
  11. <br />
  12. <div class="common-box list-box">
  13. <div class="title-box">
  14. <!-- 人群定向 -->
  15. <h3 style="width: 120px" v-if="type === 'crowd'">人群包</h3>
  16. <h3 style="width: 184px" v-else>定向包</h3>
  17. <h3 style="width: 100px" v-if="type === 'crowd'">创建时间</h3>
  18. <h3 :style="type === 'crowd' ? 'width: 70px' : 'width: 90px'">操作</h3>
  19. </div>
  20. <div class="list">
  21. <a-empty v-show="list.length == 0"></a-empty>
  22. <!-- 人群定向循环列表 -->
  23. <p v-for="item in list" :key="item.id">
  24. <span
  25. v-if="type === 'crowd'"
  26. :title="item.name"
  27. style="width: 110px"
  28. class="item-name"
  29. >{{ item.name }}</span
  30. >
  31. <span
  32. v-else
  33. :title="item.name"
  34. style="width: 180px"
  35. class="item-name"
  36. >{{ item.name }}</span
  37. >
  38. <span
  39. style="width: 100px; margin: 0 20px 0 10px"
  40. v-if="type === 'crowd'"
  41. >{{ item.time }}</span
  42. >
  43. <span :style="'width:' + type === 'crowd' ? '70px' : '90px'">
  44. <a-button
  45. style="padding: 4px"
  46. type="link"
  47. @click="addDirection(item)"
  48. :disabled="directionList.idList.includes(item.id)"
  49. >定向</a-button
  50. >
  51. <a-button
  52. style="padding: 0"
  53. type="link"
  54. @click="addExclusion(item)"
  55. :disabled="exclusionList.idList.includes(item.id)"
  56. >排除</a-button
  57. >
  58. </span>
  59. </p>
  60. </div>
  61. </div>
  62. <div class="common-box selected-box">
  63. <div class="title-box">
  64. <span
  65. style="
  66. display: block;
  67. font-weight: bold;
  68. line-height: 30px;
  69. float: left;
  70. font-size: 13px;
  71. "
  72. >已选</span
  73. >
  74. <h3 class="clear-all" @click="clearAll">全部清空</h3>
  75. </div>
  76. <div class="tabs">
  77. <span
  78. :class="selectedKey === 'direction' ? 'tabs-active' : ''"
  79. @click="selectedKey = 'direction'"
  80. >定向({{ directionList.itemList.length }})</span
  81. >
  82. <span
  83. :class="selectedKey === 'exclusion' ? 'tabs-active' : ''"
  84. @click="selectedKey = 'exclusion'"
  85. >排除({{ exclusionList.itemList.length }})</span
  86. >
  87. </div>
  88. <div class="selected-item">
  89. <div v-show="selectedKey === 'direction'">
  90. <p v-for="item in directionList.itemList" :key="item.id">
  91. <span>{{ item.name }}</span>
  92. <i
  93. class="iconfont icon-guanbi"
  94. @click="deleteDirectionItem(item.id)"
  95. ></i>
  96. </p>
  97. </div>
  98. <div v-show="selectedKey === 'exclusion'">
  99. <p v-for="item in exclusionList.itemList" :key="item.id">
  100. <span>{{ item.name }}</span>
  101. <i
  102. class="iconfont icon-guanbi"
  103. @click="deleteExclusionItem(item.id)"
  104. ></i>
  105. </p>
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. </template>
  111. <script lang="ts">
  112. import { defineComponent, reactive, toRefs, ref } from "vue";
  113. import { getMediaPackage } from "@/api";
  114. import { message } from "ant-design-vue";
  115. // 1691995913023502
  116. const DirectionExclusion = defineComponent({
  117. props: ["compType"],
  118. setup() {
  119. const state = reactive({
  120. search: "", // 过滤
  121. selectedKey: "direction",
  122. type: "crowd", // 人群组件/媒体组件
  123. list: ref<any[]>([]),
  124. originList: [
  125. {
  126. name: "测试人群包A测试人群包A测试人群包A",
  127. time: "2020-01-10",
  128. id: 1,
  129. },
  130. {
  131. name: "测试人群包B",
  132. time: "2020-01-10",
  133. id: 2,
  134. },
  135. {
  136. name: "测试人群包B",
  137. time: "2020-01-10",
  138. id: 3,
  139. },
  140. {
  141. name: "测试人群包B",
  142. time: "2020-01-10",
  143. id: 4,
  144. },
  145. {
  146. name: "测试人群包B",
  147. time: "2020-01-10",
  148. id: 5,
  149. },
  150. {
  151. name: "测试人群包B",
  152. time: "2020-01-10",
  153. id: 6,
  154. },
  155. {
  156. name: "测试人群包B",
  157. time: "2020-01-10",
  158. id: 7,
  159. },
  160. {
  161. name: "测试人群包B",
  162. time: "2020-01-10",
  163. id: 8,
  164. },
  165. ],
  166. directionList: {
  167. itemList: ref<any[]>([]), // 渲染数组
  168. idList: ref<any[]>([]), // 传参数组
  169. },
  170. exclusionList: {
  171. itemList: ref<any[]>([]), // 渲染数组
  172. idList: ref<any[]>([]), // 传参数组
  173. },
  174. });
  175. return { ...toRefs(state) };
  176. },
  177. mounted() {
  178. this.type = this.$props.compType === "media" ? "media" : "crowd";
  179. this.list = JSON.parse(JSON.stringify(this.originList));
  180. this.getList();
  181. },
  182. methods: {
  183. async getList() {
  184. this.list = [];
  185. let { data } = await getMediaPackage({
  186. advertiser_id: this.$route.query.advertiser_id,
  187. page: 1,
  188. page_size: 99,
  189. });
  190. console.log("定向包数据", data);
  191. if (data.list.length > 0) {
  192. data.list.forEach((item: any) => {
  193. this.list.push({ name: item.name, id: item.flow_package_id });
  194. });
  195. }
  196. },
  197. // 添加定向
  198. addDirection(val: any) {
  199. this.directionList.itemList.push(val);
  200. this.directionList.idList.push(val.id);
  201. if (this.exclusionList.idList.includes(val.id)) {
  202. this.deleteExclusionItem(val.id);
  203. }
  204. this.selectedKey = "direction";
  205. },
  206. // 添加排除
  207. addExclusion(val: any) {
  208. this.exclusionList.itemList.push(val);
  209. this.exclusionList.idList.push(val.id);
  210. if (this.directionList.idList.includes(val.id)) {
  211. this.deleteDirectionItem(val.id);
  212. }
  213. this.selectedKey = "exclusion";
  214. },
  215. // 全部删除
  216. clearAll() {
  217. this.directionList.itemList = [];
  218. this.directionList.idList = [];
  219. this.exclusionList.itemList = [];
  220. this.exclusionList.idList = [];
  221. },
  222. // 根据id删除定向项
  223. deleteDirectionItem(id: any) {
  224. this.directionList.idList.splice(
  225. this.directionList.idList.indexOf(id),
  226. 1
  227. );
  228. this.directionList.itemList.forEach((item: any) => {
  229. if (item.id === id) {
  230. this.directionList.itemList.splice(
  231. this.directionList.itemList.indexOf(item),
  232. 1
  233. );
  234. }
  235. });
  236. },
  237. // 根据id删除排除项
  238. deleteExclusionItem(id: any) {
  239. this.exclusionList.idList.splice(
  240. this.exclusionList.idList.indexOf(id),
  241. 1
  242. );
  243. this.exclusionList.itemList.forEach((item: any) => {
  244. if (item.id === id) {
  245. this.exclusionList.itemList.splice(
  246. this.exclusionList.itemList.indexOf(item),
  247. 1
  248. );
  249. }
  250. });
  251. },
  252. // 返回过滤结果
  253. onSearch() {
  254. this.list = this.originList.filter((item: any) => {
  255. return (
  256. item.name.indexOf(this.search) > -1 ||
  257. item.id.indexOf(this.search) > -1
  258. );
  259. });
  260. },
  261. // 获取父组件数据回显
  262. showData(directionArr: any, exclusionArr: any) {
  263. if (directionArr.length > 0) {
  264. this.list.forEach((item) => {
  265. if (directionArr.includes(item.value)) {
  266. this.directionList.idList.push(item.value);
  267. this.directionList.itemList.push(item);
  268. }
  269. });
  270. }
  271. if (exclusionArr.length > 0) {
  272. this.list.forEach((item) => {
  273. if (exclusionArr.includes(item.value)) {
  274. this.exclusionList.idList.push(item.value);
  275. this.exclusionList.itemList.push(item);
  276. }
  277. });
  278. }
  279. },
  280. // 返回给父组件数据
  281. backData() {
  282. console.log(this.directionList);
  283. let data = {
  284. direction: this.directionList.idList,
  285. exclusion: this.exclusionList.idList,
  286. };
  287. return data;
  288. },
  289. },
  290. });
  291. export default DirectionExclusion;
  292. </script>
  293. <style lang="scss" scoped>
  294. .direction-exclusion {
  295. width: 560px;
  296. overflow: hidden;
  297. .common-box {
  298. height: 210px;
  299. float: left;
  300. border: 1px solid rgb(210, 210, 210);
  301. border-radius: 2px;
  302. .title-box {
  303. padding: 0 10px;
  304. height: 30px;
  305. border-bottom: 1px solid rgb(210, 210, 210);
  306. h3 {
  307. font-size: 13px;
  308. font-weight: bold;
  309. height: 30px;
  310. line-height: 30px;
  311. float: left;
  312. margin-bottom: 0;
  313. }
  314. .clear-all {
  315. font-size: 13px;
  316. font-weight: normal;
  317. color: gray;
  318. float: right;
  319. cursor: pointer;
  320. }
  321. }
  322. .list {
  323. height: 180px;
  324. padding: 4px 10px;
  325. overflow: auto;
  326. p {
  327. height: 28px;
  328. line-height: 28px;
  329. .item-name {
  330. display: block;
  331. float: left;
  332. white-space: nowrap;
  333. text-overflow: ellipsis;
  334. overflow: hidden;
  335. word-break: break-all;
  336. }
  337. }
  338. }
  339. }
  340. .list-box {
  341. width: 320px;
  342. }
  343. .selected-box {
  344. width: 200px;
  345. margin-left: 20px;
  346. .tabs {
  347. width: 100%;
  348. display: flex;
  349. justify-content: space-around;
  350. span {
  351. cursor: pointer;
  352. display: inline-block;
  353. line-height: 30px;
  354. }
  355. .tabs-active {
  356. color: rgb(80, 138, 245);
  357. border-bottom: 3px solid rgb(80, 138, 245);
  358. }
  359. }
  360. .selected-item {
  361. height: 140px;
  362. padding: 0px 10px;
  363. overflow: auto;
  364. p {
  365. background: rgb(240, 240, 240);
  366. height: 26px;
  367. line-height: 26px;
  368. display: flex;
  369. align-items: center;
  370. justify-content: space-around;
  371. margin-top: 6px;
  372. font-size: 13px;
  373. span {
  374. display: inline-block;
  375. width: 130px;
  376. white-space: nowrap;
  377. text-overflow: ellipsis;
  378. overflow: hidden;
  379. word-break: break-all;
  380. border-radius: 2px;
  381. }
  382. i {
  383. cursor: pointer;
  384. font-size: 13px;
  385. &:hover {
  386. color: skyblue;
  387. }
  388. }
  389. }
  390. }
  391. }
  392. }
  393. </style>