SubConfig.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. <template>
  2. <div class="subscribe-config">
  3. <div class="sub-title">订阅设置</div>
  4. <div class="sub-content">
  5. <!-- <div class="item">
  6. <div class="item-label item-label-required">区域:</div>
  7. <div class="item-value" @click="clickErea">
  8. <el-input class="custom-long-input" v-model="areaStr" readonly unselectable="on"></el-input>
  9. </div>
  10. </div> -->
  11. <div class="item">
  12. <div class="item-label item-label-required">区域:</div>
  13. <div class="item-value">
  14. <AreaCityCountryCascader
  15. ref="areaCityCountrySub"
  16. stopDropdown
  17. showSelected
  18. showCount
  19. :areaCount="areaCount"
  20. :initMap="regionMapData"
  21. @onClick="onAreaSelectClick"
  22. @change="onAreaCityCountryChange"
  23. @exceed="onExceedChange"
  24. >
  25. <div slot="header"></div>
  26. </AreaCityCountryCascader>
  27. </div>
  28. </div>
  29. <div class="item">
  30. <div class="item-label item-label-required">采购单位类型:</div>
  31. <div class="item-value" @click="dialog.buyClass = true">
  32. <el-input
  33. class="custom-long-input"
  34. v-model="buyClassStr"
  35. readonly
  36. unselectable="on"
  37. ></el-input>
  38. </div>
  39. </div>
  40. <div class="item">
  41. <div class="item-label item-label-required">信息类型:</div>
  42. <div class="item-value" @click="dialog.infoType = true">
  43. <el-input
  44. class="custom-long-input"
  45. v-model="infoTypeStr"
  46. readonly
  47. unselectable="on"
  48. ></el-input>
  49. </div>
  50. </div>
  51. <div class="item-other">
  52. <div class="item-label">项目匹配:</div>
  53. <div class="item-value item-other-value">
  54. <el-switch
  55. @change="switchProjectMatch($event)"
  56. v-model="projectMatchData"
  57. :width="44"
  58. :active-value="1"
  59. :inactive-value="0"
  60. active-text="关"
  61. inactive-text="开"
  62. active-color="#2cb7ca"
  63. inactive-color="#bfbfbf"
  64. >
  65. </el-switch>
  66. <p class="math-tips">
  67. 开启后,系统将根据你订阅的关键词自动匹配出相关联的项目,并将相关连项目的后续动态在超级订阅内一并推送。
  68. </p>
  69. </div>
  70. </div>
  71. <div class="item-other">
  72. <div class="item-label">关键词匹配方式:</div>
  73. <div class="item-value item-other-value">
  74. <el-radio-group
  75. v-model="matchWayData"
  76. @change="chooseMatchWay($event)"
  77. >
  78. <div class="radio-item">
  79. <el-radio name="matchway" :label="1">按标题匹配</el-radio>
  80. </div>
  81. <div>
  82. <el-radio name="matchway" :label="2">按全文匹配</el-radio>
  83. </div>
  84. </el-radio-group>
  85. <p class="math-tips">会产生无效信息,请根据需要选择</p>
  86. </div>
  87. </div>
  88. </div>
  89. <!-- 区域选择dialog -->
  90. <el-dialog
  91. custom-class="sub-dialog nesting-dialog r70"
  92. :visible.sync="dialog.area"
  93. :close-on-click-modal="false"
  94. :show-close="false"
  95. center
  96. width="460px"
  97. v-component-change-mount="{ selector: '.drawer-dialog' }"
  98. >
  99. <AreaSelect
  100. :initCityMap="areaData"
  101. :showSelectResult="true"
  102. :areaCount="areaCount"
  103. :canSetCityCount="canSetCityCount"
  104. :showSelectedDetail="false"
  105. @onCancel="dialog.area = false"
  106. @onConfirm="saveAreaData"
  107. >
  108. <template #update-tips>
  109. <span @click="onClickUpdateTip" v-if="!entStatus"
  110. >超出已购买省份数量,您可前往升级超级订阅>
  111. </span>
  112. </template>
  113. </AreaSelect>
  114. </el-dialog>
  115. <!-- 采购单位行业dialog -->
  116. <el-dialog
  117. custom-class="sub-dialog nesting-dialog r70"
  118. :visible.sync="dialog.buyClass"
  119. :close-on-click-modal="false"
  120. :show-close="false"
  121. center
  122. width="460px"
  123. v-component-change-mount="{ selector: '.drawer-dialog' }"
  124. >
  125. <BuyClassSelect
  126. :initCate="buyerClassData"
  127. :otherMatch="otherBuyerClassData"
  128. getContainer=".drawer-dialog"
  129. @onCancel="dialog.buyClass = false"
  130. @onConfirm="saveBuyClassData"
  131. @onOtherConfirm="saveOtherBuyClass"
  132. >
  133. <div slot="header">选择采购单位类型</div>
  134. </BuyClassSelect>
  135. </el-dialog>
  136. <!-- 信息类型dialog -->
  137. <el-dialog
  138. custom-class="sub-dialog nesting-dialog r70"
  139. :visible.sync="dialog.infoType"
  140. :close-on-click-modal="false"
  141. :show-close="false"
  142. center
  143. width="460px"
  144. v-component-change-mount="{ selector: '.drawer-dialog' }"
  145. >
  146. <InfoTypeSelect
  147. :initInfoType="infoTypeData"
  148. @onCancel="dialog.infoType = false"
  149. @onConfirm="saveInfoTypeData"
  150. >
  151. <div slot="header">选择信息类型</div>
  152. </InfoTypeSelect>
  153. </el-dialog>
  154. <el-dialog
  155. :visible.sync="dialog.areaMap"
  156. title="超出可选省份数量"
  157. :show-close="false"
  158. class="tip-dialog"
  159. width="380px"
  160. top="30vh"
  161. center
  162. v-component-change-mount="{ selector: '.drawer-dialog' }"
  163. >
  164. <div>
  165. 可选:<span class="highlight-text">{{ areaCount }}个省</span
  166. >,如需增加省份数量,您可前往升级超级订阅。
  167. </div>
  168. <div slot="footer" class="dialog-footer">
  169. <el-button type="primary" @click.stop="goUpdateVip">去升级</el-button>
  170. <el-button @click="dialog.areaMap = false">取 消</el-button>
  171. </div>
  172. </el-dialog>
  173. <popupBox
  174. ref="popupBox"
  175. text="如需修改区域,请联系企业管理员修改分发设置区域。"
  176. title="不支持修改区域"
  177. :appendtoBody="false"
  178. ></popupBox>
  179. </div>
  180. </template>
  181. <script>
  182. import { Switch, Input, RadioGroup, Radio, Button, Dialog } from 'element-ui'
  183. import AreaSelect from '@/components/selector/AreaSelector'
  184. import BuyClassSelect from '@/components/selector/BuyerclassSelector'
  185. import InfoTypeSelect from '@/components/selector/InfoTypeSelector'
  186. import popupBox from '@/components/common/popupBox'
  187. import AreaCityCountryCascader from '@/components/selector-cascader/AreaCityCountryCascader.vue'
  188. import { userRule, entBaseInfo } from '@/api/modules'
  189. import { openSelfLink } from '@/utils/'
  190. export default {
  191. name: 'sub-config',
  192. props: {
  193. projectMatch: [String, Number, Boolean],
  194. otherBuyerClass: [String, Number, Boolean],
  195. matchWay: [String, Number, Boolean],
  196. area: Object,
  197. buyerClass: Array,
  198. infoType: Array,
  199. areaCount: Number,
  200. canSetCityCount: Number,
  201. regionMap: Object
  202. },
  203. components: {
  204. [Switch.name]: Switch,
  205. [Input.name]: Input,
  206. [RadioGroup.name]: RadioGroup,
  207. [Radio.name]: Radio,
  208. [Button.name]: Button,
  209. [Dialog.name]: Dialog,
  210. AreaSelect,
  211. BuyClassSelect,
  212. InfoTypeSelect,
  213. popupBox,
  214. AreaCityCountryCascader
  215. },
  216. data() {
  217. return {
  218. areaStr: '',
  219. buyClassStr: '',
  220. infoTypeStr: '',
  221. projectMatchData: this.projectMatch,
  222. matchWayData: this.matchWay,
  223. otherBuyerClassData: this.otherBuyerClass,
  224. areaData: this.area,
  225. buyerClassData: this.buyerClass,
  226. infoTypeData: this.infoType,
  227. dialog: {
  228. area: false,
  229. buyClass: false,
  230. infoType: false,
  231. areaMap: false
  232. },
  233. timeout: null,
  234. entStatus: false,
  235. districtMapData: {},
  236. areaMapData: this.area,
  237. regionMapData: this.regionMap
  238. }
  239. },
  240. watch: {
  241. projectMatch(n) {
  242. this.projectMatchData = n
  243. },
  244. otherBuyerClass(n) {
  245. this.otherBuyerClassData = n
  246. },
  247. matchWay(n) {
  248. this.matchWayData = n
  249. },
  250. area(n) {
  251. this.areaData = n
  252. this.initData()
  253. },
  254. buyerClass(n) {
  255. this.buyerClassData = n
  256. this.initData()
  257. },
  258. infoType(n) {
  259. this.infoTypeData = n
  260. this.initData()
  261. },
  262. regionMap(n) {
  263. this.regionMapData = n
  264. }
  265. },
  266. computed: {
  267. formatAreaMap() {
  268. const original = this.areaData
  269. // 原二级数据结构为{福建:['福州', '厦门', '宁德']}
  270. // 现数据结构为三级 需进行处理
  271. if (Object.keys(original).length > 0) {
  272. const obj = {}
  273. for (const province in original) {
  274. let cityMap = {}
  275. if (Array.isArray(original[province])) {
  276. original[province].forEach((city) => {
  277. cityMap[city] = []
  278. })
  279. } else {
  280. cityMap = original[province]
  281. }
  282. obj[province] = cityMap
  283. }
  284. return obj
  285. } else {
  286. return original
  287. }
  288. }
  289. },
  290. mounted() {
  291. this.initData()
  292. },
  293. methods: {
  294. debounce(fn, delay) {
  295. if (this.timeout) {
  296. clearTimeout(this.timeout)
  297. }
  298. this.timeout = setTimeout(() => {
  299. fn()
  300. }, delay)
  301. },
  302. onClickUpdateTip() {
  303. const routeUrl = this.$router.resolve({
  304. path: '/free/svip/buy?type=upgrade'
  305. })
  306. openSelfLink(routeUrl)
  307. },
  308. clickErea() {
  309. this.debounce(() => {
  310. entBaseInfo({}).then((res) => {
  311. if (
  312. res.data.vip_power === 1 ||
  313. res.data.member_power === 1 ||
  314. res.data.user_power === 1
  315. ) {
  316. // 企业授权
  317. this.entStatus = true // 切换身份为 企业身份下
  318. userRule().then((res_) => {
  319. if (res_.data) {
  320. // 设置了区域
  321. this.$refs.popupBox.isshow = true
  322. } else {
  323. this.dialog.area = true
  324. }
  325. })
  326. } else {
  327. // 非企业授权
  328. this.dialog.area = true
  329. }
  330. })
  331. }, 200)
  332. },
  333. initData() {
  334. // this.formatterArea(this.area)
  335. this.formatterBuyerClass(this.buyerClass)
  336. this.formatterInfoType(this.infoType)
  337. },
  338. // 处理区域数据
  339. formatterArea(area = {}) {
  340. if (area && Object.keys(area).length > 0) {
  341. const provinceArr = []
  342. let areaArr = []
  343. for (const key in area) {
  344. provinceArr.push({
  345. province: key,
  346. citys: area[key]
  347. })
  348. }
  349. provinceArr.forEach((province, i) => {
  350. const cityArr = []
  351. let pStr = ''
  352. province.citys.forEach((city, ii) => {
  353. cityArr.push(city)
  354. })
  355. if (cityArr.length === 0) {
  356. pStr = province.province
  357. } else {
  358. pStr = province.province + '(' + cityArr.join('、') + ')'
  359. }
  360. areaArr.push(pStr)
  361. })
  362. areaArr = areaArr.join('、')
  363. this.areaStr = areaArr
  364. } else {
  365. this.areaStr = '全国'
  366. }
  367. },
  368. formatterBuyerClass(data = []) {
  369. if (data && data.length > 0) {
  370. this.buyClassStr =
  371. data.join('、') + (this.otherBuyerClassData ? '、匹配未分类行业' : '')
  372. } else {
  373. this.buyClassStr =
  374. '全部' + (this.otherBuyerClassData ? '、匹配未分类类型' : '')
  375. }
  376. },
  377. formatterInfoType(data = []) {
  378. if (data && data.length > 0) {
  379. this.infoTypeStr = data.join('、')
  380. } else {
  381. this.infoTypeStr = '全部类型'
  382. }
  383. },
  384. // 切换项目匹配按钮
  385. switchProjectMatch(event) {
  386. this.projectMatchData = event
  387. this.saveCommonData()
  388. },
  389. // 关键词匹配方式
  390. chooseMatchWay(event) {
  391. this.matchWayData = event
  392. this.saveCommonData()
  393. },
  394. // 冒泡区域修改数据
  395. saveAreaData(data) {
  396. this.areaData = data
  397. // this.formatterArea(data)
  398. this.dialog.area = false
  399. this.saveCommonData()
  400. },
  401. // 冒泡采购单位行业数据及匹配未分类行业数据
  402. saveBuyClassData(data) {
  403. this.buyerClassData = data
  404. this.formatterBuyerClass(data)
  405. this.saveCommonData()
  406. this.dialog.buyClass = false
  407. },
  408. // 冒泡未匹配采购单位行业
  409. saveOtherBuyClass(data) {
  410. this.otherBuyerClassData = data.selected ? 1 : 0
  411. this.formatterBuyerClass(this.buyerClassData)
  412. this.saveCommonData()
  413. },
  414. // 冒泡信息类型数据
  415. saveInfoTypeData(data) {
  416. this.infoTypeData = data
  417. this.formatterInfoType(data)
  418. this.saveCommonData()
  419. this.dialog.infoType = false
  420. },
  421. saveCommonData() {
  422. this.$emit('update', {
  423. // area: this.areaData,
  424. area: this.areaMapData,
  425. buyerClass: this.buyerClassData,
  426. infotype: this.infoTypeData,
  427. projectmatch: this.projectMatchData,
  428. matchway: this.matchWayData,
  429. otherbuyerclass: this.otherBuyerClassData,
  430. district: this.districtMapData,
  431. regionMap: this.regionMapData
  432. })
  433. },
  434. // 省市区组件回调数据
  435. onAreaCityCountryChange(data) {
  436. const { area, district, regionMap } = data
  437. this.areaMapData = area
  438. this.districtMapData = district
  439. this.regionMapData = regionMap
  440. this.saveCommonData()
  441. },
  442. // 区域选择超出冒泡事件
  443. onExceedChange() {
  444. this.dialog.areaMap = true
  445. },
  446. async onAreaSelectClick() {
  447. const { data } = await entBaseInfo()
  448. if (
  449. data.vip_power === 1 ||
  450. data.member_power === 1 ||
  451. data.user_power === 1
  452. ) {
  453. // 企业授权
  454. const { data: flag } = await userRule()
  455. if (flag) {
  456. this.$refs.popupBox.isshow = true
  457. } else {
  458. this.$refs.areaCityCountrySub.toggleSelect()
  459. }
  460. } else {
  461. this.$refs.areaCityCountrySub.toggleSelect()
  462. }
  463. },
  464. // 去升级
  465. goUpdateVip() {
  466. window.open('/swordfish/page_big_pc/free/svip/buy?type=upgrade')
  467. }
  468. }
  469. }
  470. </script>
  471. <style lang="scss" scoped>
  472. .subscribe-config {
  473. background: #fff;
  474. .sub-title {
  475. padding: 26px 30px;
  476. font-size: 18px;
  477. color: #1d1d1d;
  478. line-height: 28px;
  479. border-bottom: 1px solid #ececec;
  480. }
  481. .sub-content {
  482. padding: 20px 0;
  483. }
  484. .item {
  485. display: flex;
  486. align-items: center;
  487. justify-content: center;
  488. margin-bottom: 10px;
  489. }
  490. .item-label {
  491. margin-right: 8px;
  492. min-width: 120px;
  493. height: 40px;
  494. color: #1d1d1d;
  495. font-size: 14px;
  496. line-height: 40px;
  497. text-align: right;
  498. }
  499. .item-label-required:before {
  500. content: '*';
  501. color: #f56c6c;
  502. margin-right: 2px;
  503. }
  504. .item-value {
  505. width: 352px;
  506. }
  507. .custom-long-input {
  508. width: 352px;
  509. }
  510. .item-other {
  511. display: flex;
  512. justify-content: center;
  513. margin-bottom: 10px;
  514. }
  515. .item-other-value {
  516. margin-top: 8px;
  517. }
  518. .math-tips {
  519. margin-top: 4px;
  520. font-size: 12px;
  521. color: #999999;
  522. line-height: 20px;
  523. }
  524. .radio-item {
  525. margin-bottom: 10px;
  526. }
  527. // element-ui样式修改
  528. ::v-deep {
  529. .custom-long-input .el-input__inner {
  530. font-size: 14px;
  531. color: #2cb7ca;
  532. white-space: nowrap;
  533. overflow: hidden;
  534. text-overflow: ellipsis;
  535. border-color: #ececec;
  536. }
  537. .el-loading-spinner .circular {
  538. width: 22px;
  539. height: 22px;
  540. }
  541. .el-loading-spinner {
  542. margin-top: -11px;
  543. }
  544. .el-input__inner {
  545. background: #fff;
  546. cursor: pointer;
  547. }
  548. .el-switch {
  549. position: relative;
  550. }
  551. .el-switch__label--left {
  552. position: absolute;
  553. left: 6px;
  554. top: 0;
  555. color: #fff;
  556. z-index: 9;
  557. font-size: 12px;
  558. }
  559. .el-switch__label--right {
  560. position: absolute;
  561. right: 6px;
  562. top: 0;
  563. color: #fff;
  564. z-index: 9;
  565. font-size: 12px;
  566. }
  567. .el-switch__label * {
  568. font-size: 12px;
  569. }
  570. .el-switch,
  571. .el-switch__core {
  572. height: 22px;
  573. line-height: 22px;
  574. }
  575. .el-switch__core:after {
  576. width: 18px;
  577. height: 18px;
  578. }
  579. .el-switch.is-checked .el-switch__core::after {
  580. margin-left: -18px !important;
  581. }
  582. .el-radio {
  583. color: #1d1d1d;
  584. font-size: 14px;
  585. }
  586. .el-radio__inner {
  587. width: 20px;
  588. height: 20px;
  589. }
  590. .el-radio__input.is-checked .el-radio__inner {
  591. border: 0;
  592. background: transparent;
  593. width: 20px;
  594. height: 20px;
  595. background: url('~@/assets/images/icon-checked.png') no-repeat center
  596. center;
  597. background-size: contain;
  598. }
  599. .el-radio__inner::after {
  600. background: transparent;
  601. }
  602. .el-radio__input.is-checked + .el-radio__label {
  603. color: #1d1d1d;
  604. }
  605. .el-radio__inner:hover {
  606. border-color: #ececec;
  607. }
  608. .s-header {
  609. display: none;
  610. }
  611. .area-city-country {
  612. padding: 0 !important;
  613. }
  614. .el-select {
  615. width: 100%;
  616. .el-input__inner {
  617. height: 40px;
  618. line-height: 40px;
  619. }
  620. .select-prefix {
  621. height: 38px;
  622. line-height: 38px;
  623. }
  624. }
  625. }
  626. }
  627. </style>