PageSourceSearch

https://www.szumao.com/assets/js/unit/affiliate.js

js szumao.com collected 2026-10-09 00:49:18 UTC 67,256 bytes, 1,848 lines download raw bytes

1class ScriptAffiliate extends Script {
2  constructor(params) {
3    super(params)
4    this.site_id = window.app.info.site.site_id
5    this.$t = window.app.utilts.$t
6  }
7  /** 初始化,支持异步 */
8  async init() {
9    const _that = this
10    if (!window.LFSDK.isLogin()){
11      window.location.href = globalThis.Server.getRinseHref(`/login.html`, window.app.info.site)
12      return
13    }
14    await new Load('/assets/plugins/vue.min.js')
15    new Vue({
16      el: `#${_that.attrId} .unit-user__app`,
17      mixins: [
18        _that.basicData,
19        _that.myAccountData,
20        _that.withdrawalData,
21        _that.commissionData,
22        _that.messageData,
23        _that.shareProductData,
24        _that.ordersReportData,
25        _that.LinksReportData,
26        _that.promotionReportData,
27        _that.excelHandlerData
28      ],
29      data: {
30        site_id:_that.site_id,
31        attrId:_that.attrId,
32        tool: ScriptCommonUtil.ins(),
33        api: ScriptAffiliateApi.ins(),
34        loadingPage:true,
35        moneyUnit: 'US $',
36        rowBannerImg:'',
37        rowBannerUrl:'',
38        eventname:window.app.info.client.is_mobile ? 'touchstart' : 'click',
39        // 分页
40        page_input_blur:false,
41        page_count: 1, //总页数
42        page_number:1, // 当前页
43        page_size:10, // 每页条数
44        total:0 // 总数据条数
45      },
46      created() {
47        this.initPage()
48        this.getBannerInfo()
49      },
50      watch: {
51        thisView(val) {
52          for(let i = 0;i < this.sideNav.length;i++) {
53            let nav = this.sideNav[i].list.find(ite=> ite.view === val)
54            if (nav) {
55              this.$set(this.breadcrumb, 1, { title: nav.title, href: globalThis.Server.getRinseHref(`/affiliate.html#${val}`, window.app.info.site) })
56              break
57            }
58          }
59        }
60      },
61      filters: {
62        priceFormat(val,n = 2) {
63          if (isNaN(val)) val = 0
64          let tempVal = val
65          if (val < 0) tempVal = -tempVal
66          return val < 0 ? '-' + ((tempVal / 100).toFixed(n)) : (tempVal / 100).toFixed(n)
67        },
68        addComma(num) {
69          // 金融逗号分割
70          const res = num.toString().replace(/\d+/, n => { // 先提取整数部分
71            return n.replace(/(\d)(?=(\d{3})+$)/g, $1 =>{
72              return $1+","
73            })
74          })
75          return res
76        },
77        keyFormat(val) {
78          let v = val
79          switch(val) {
80            case 'country': v = 'Country';break;
81            case 'bank_name': v = 'bank name';break;
82            case 'swift_code': v = 'swift code';break;
83            case 'account_name': v = 'Account Name';break;
84            case 'bank_address': v = 'bank address';break;
85            case 'currency_type': v = 'Currency Type';break;
86            case 'account_number': v = 'Account Number';break;
87            case 'upload_invoice': v = 'Upload Invoice';break;
88          }
89          return _that.$t(v)
90        }
91      },
92      methods: {
93        // 横幅信息
94        async getBannerInfo() {
95          const res = await this.api.doublePromise('getDistributeConfigDesignDetail',{site_id:this.sign,sign:'account_page_design'})
96          if (res.code === 0) {
97            this.rowBannerImg = res.data.banner_img || ''
98            this.rowBannerUrl = res.data.banner_url || ''
99          }
100        },
101        // 分页
102        async changePageIndex(v, t = '') {
103          // 处理同时失焦和点击按钮连续两次触发问题
104          if (this.page_input_blur) return
105          if (t === 'blur') {
106            this.page_input_blur = true
107            setTimeout(()=> this.page_input_blur = false,500)
108          }
109          if (v !== 'go') {
110            if ((v === 'prev' && this.page_number === 1) || (v === 'next' && this.page_number === this.page_count)) return 
111            if (v === 'prev' && this.page_number > 1) this.page_number -= 1
112            else if (v === 'next' && this.page_number < this.page_count) this.page_number += 1
113            else this.page_number = Number(v)
114          }
115          if (isNaN(this.page_number) || this.page_number < 1) this.page_number = 1
116          else if (this.page_number > this.page_count) this.page_number = this.page_count
117          else this.page_number = Number(this.page_number)
118          // 执行分页对应接口函数
119          switch(this.thisView) {
120            case 'message':
121            case 'faq':
122            case 'tutorial': await this.loadMessageApi();break;
123            case 'share_product':await this.loadShareProductApi();break;
124            case 'orders_report':await this.loadOrdersReportApi();break;
125            case 'links_report':await this.loadLinksReportApi();break;
126            case 'commission_details':await this.loadCommissionApi();break;
127          }
128        },
129        // 点击侧边栏 from: 来自哪里点击(侧边栏/按钮)
130        async toView(view,from = '') {
131          if (this.loadingPage) {
132            this.tool.showTips('You are clicking too fast','warn')
133            return
134          }
135          this.thisView = view
136          location.hash = view
137          this.loadingPage = true
138          await this.loadPageApi(from)
139          this.loadingPage = false
140        },
141        // 初始化页面
142        async initPage() {
143          if (location.hash.length > 0) this.thisView = location.hash.split('?')[0].replace('#', '')
144          else this.thisView = 'account'
145          this.loadingPage = true
146          await this.loadPageApi()
147          this.loadingPage = false
148        },
149        // 初始化页面的数据
150        initPageData(v) {
151          // 分页数据
152          this.pagingInitData()
153          // 页面数据
154          switch(v) {
155            case 'account': this.accountInitData(); break;
156            case 'message':
157            case 'faq':
158            case 'tutorial': this.messageInitData(); break;
159            case 'share_product': this.shareProductInitData(); break;
160            case 'orders_report': this.ordersReportInitData(); break;
161            case 'links_report': this.linksReportInitData(); break;
162            case 'promotion_reports': this.promotionReportInitData(); break;
163            case 'commission_details': this.commissionDetailInitData(); break;
164          }
165        },
166        // 加载页面接口
167        loadPageApi(from = '') {
168          const v = this.thisView
169          return new Promise(async resolve => {
170            // 初始化数据
171            this.initPageData(v)
172
173            if (v !== 'account') {
174              const res = await this.api.doublePromise('getDistributeMemberStatus')
175              // 获取分销员开启状态
176              if (res.code !== 0 || res.data !== 1) {
177                new Modal().confirm(_that.$t('The account has been deactivated, please contact customer service to activate'), _that.$t('Tips'), { isHideCancel:true, isCloseNoCancel: true })
178                .then(async() => {
179                  window.location.href = globalThis.Server.getRinseHref('/user.html', window.app.info.site)
180                }).catch(err=> {})
181                setTimeout(()=>{ window.location.href = globalThis.Server.getRinseHref('/user.html', window.app.info.site) }, 3000)
182                return
183              }
184              // 优先获取分销账户信息以便需要处获取分销员id
185              if (!this.accountInfo.id) await this.getAccountInfo()
186            }
187            switch(v) {
188              case 'account':
189                if (from !== 'btn') this.accountView = 'index'
190                await this.loadAccountApi()
191                break;
192              case 'message':
193              case 'faq':
194              case 'tutorial':
195                await this.loadMessageApi()
196                break;
197              case 'share_product':
198                await this.loadShareProductApi()
199                break;
200              case 'orders_report':
201                await this.loadOrdersReportApi()
202                break;
203              case 'promotion_reports':
204                await this.loadPromotionApi()
205                break;
206              case 'links_report':
207                await this.loadLinksReportApi()
208                break;
209              case 'commission_details':
210                if (from !== 'btn') {
211                  this.commissionView = 'index'
212                  this.commissionTab = 0
213                }
214                await this.loadCommissionApi()
215                break;
216            }
217            resolve()
218          })
219        },
220        // 分页初始化数据
221        pagingInitData() {
222          this.page_number = 1
223          this.page_size = 10
224          this.page_count = 1
225          this.total = 0
226        }
227      }
228    })
229  }
230   /** 基本信息 */
231   get basicData() {
232    const _that = this
233    return {
234      data: {
235        utilts: window.app.utilts,
236        breadcrumb: [
237          { title: _that.$t('home'), href: globalThis.Server.getRinseHref('/', window.app.info.site) },
238          { title: _that.$t('account'), href: globalThis.Server.getRinseHref(`/affiliate.html#account`, window.app.info.site) },
239          { title: '', href: '' }
240        ],
241        thisView: 'account',
242        // 侧边栏
243        sideNav: [
244          {
245            title: _that.$t('basic information'),
246            list:[
247              { title: _that.$t('my account'), view: 'account' },
248              { title: _that.$t('message'), view: 'message' }
249            ]
250          },
251          {
252            title: _that.$t('Affiliate Guidance'),
253            list:[
254              { title: _that.$t('FAQ'), view: 'faq' },
255              { title: _that.$t('Tutorial'), view: 'tutorial' },
256              { title: _that.$t('affiliate links'), view: 'links' }
257            ]
258          },
259          {
260            title: _that.$t('promotion center'),
261            list:[
262              { title: _that.$t('Share Product'), view: 'share_product' },
263            ]
264          },
265          {
266            title: _that.$t('reports'),
267            list:[
268              { title: _that.$t('Orders Report'), view: 'orders_report' },
269              { title: _that.$t('Promotion Reports'), view: 'promotion_reports' },
270              { title: _that.$t('Links report'), view: 'links_report' },
271              { title: _that.$t('Commission Details'), view: 'commission_details' }
272            ]
273          }
274          
275        ]
276      }
277    }
278  }
279  /** 我的账户 */
280  get myAccountData() {
281    const _that = this
282    return {
283      data: {
284        accountInfo: {},
285        accountView:'index', // index、withdrawal
286        currentSwiperIndex: 1,
287        moneyPop: '',
288        howEarnData:[
289          {index:1,title:_that.$t('Choose items'),desc:_that.$t('Select premium items to increase your chances of making money')},
290          {index:2,title:_that.$t('Select how to share'),desc:_that.$t('Post the affiliate links on any of your online marketing channels: blog, Facebook, Twitter, YouTube, forums, popular social media sites, etc. Greater coverage increases potential sales.')},
291          {index:3,title:_that.$t('Received commission'),desc:_that.$t('When your buyers received and confirmed orders, you can get commission right now!')},
292          {index:4,title:_that.$t('Withdrawal'),desc:_that.$t('You can withdraw the commission to your Paypal account.')}
293        ],
294        report_date_list:[
295          {label:_that.$t('Yesterday'), value: 1},
296          {label:_that.$t('Last 7 days'), value: 2},
297          {label:_that.$t('Last 30 days'), value: 3}
298        ],
299        report_all_date_type:1,
300        report_traffic_date_type:1,
301        report_order_date_type:1,
302        report_type:'all', // all,traffic,order
303        reportSummary:{
304          link_clicks: 0,
305          promotion_order: 0,
306          effective_order: 0,
307          effective_sale_amount: 0,
308          pending_commission: 0
309        },
310        traffic_promotion_order: 0,
311        order_promotion_order: 0
312      },
313      methods:{
314        async loadAccountApi(){
315          return new Promise(async resolve => {
316            await this.getAccountInfo()
317            // 获取报告
318            this.getReportSummary()
319            resolve()
320          })
321        },
322        // params:flag (为true表示单纯获取一下最新的信息)
323        async getAccountInfo(flag = false) {
324          return new Promise(async resolve => {
325            const res = await this.api.doublePromise('getDistributeMemberInfo')
326            if (res.code === 0 && res.data.id) {
327              this.accountInfo = res.data
328              // 开启引导弹窗swiper
329              if (this.accountInfo.step_guidance_status === 1 && !flag) {
330                this.makeMoneyFun(true)
331              }
332            } else {
333              new Modal().confirm(_that.$t('The account has been deactivated, please contact customer service to activate'), _that.$t('Tips'), { isHideCancel:true, isCloseNoCancel: true })
334                .then(async() => {
335                  window.location.href = globalThis.Server.getRinseHref('/user.html', window.app.info.site)
336                }).catch(err=> {})
337                setTimeout(()=>{ window.location.href = globalThis.Server.getRinseHref('/user.html', window.app.info.site) }, 3000)
338            }
339            resolve()
340          })
341        },
342        accountInitData() {
343          this.report_all_date_type = 1
344          this.report_traffic_date_type = 1
345          this.report_order_date_type = 1
346          this.report_type = 'all'
347          this.reportSummary = {
348            link_clicks: 0,
349            promotion_order: 0,
350            effective_order: 0,
351            effective_sale_amount: 0,
352            pending_commission: 0
353          }
354          this.traffic_promotion_order = 0
355          this.order_promotion_order = 0
356          this.tool.destroySwiperHandler('how_swiper')
357          this.currentSwiperIndex = 1
358          this.withdrawalInitData()
359        },
360        // 报告相关数据
361        async getReportSummary() {
362          const rp_type =this.report_type
363          const param = {
364            date_type: this[`report_${rp_type}_date_type`],
365            type: rp_type
366          }
367          const res = await this.api.doublePromise('getDistributeMemberReportSummary', param)
368          if (res.code === 0) {
369            const obj = res.data || {}
370            const format_arr = ['effective_sale_amount', 'pending_commission']
371            for(let key in obj) {
372              this.reportSummary[key] = this.tool.numAddComma(obj[key], format_arr.includes(key))
373            }
374            if (rp_type === 'all' || rp_type === 'traffic') this.traffic_promotion_order = this.reportSummary['promotion_order']
375            if (rp_type === 'all' || rp_type === 'order') this.order_promotion_order = this.reportSummary['promotion_order']
376          }
377        },
378        // 引导弹窗
379        makeMoneyFun(flag = false) {
380          let $pop = document.querySelector(`#${_that.attrId} .how-earn-money_pop`)
381          const $app = document.querySelector('#app')
382          let isFirst = true
383          if (!$pop) {
384            if (this.moneyPop) $pop = this.moneyPop
385            else $pop = $app.querySelector('.how-earn-money_pop')
386            isFirst = false
387            if (!$pop) return
388          }
389          if (!this.moneyPop && flag && isFirst) $app.appendChild($pop)
390          $pop.classList[flag ? 'remove' : 'add']('d-none')
391          if (isFirst && flag) setTimeout(()=>{this.initHowSwiper($pop)}, 500)
392          this.moneyPop = $pop
393        },
394        // 初始化引导弹窗的swiper
395        initHowSwiper($pop) {
396          const _self = this
397          const $dom = $pop.querySelector('.how-swiper_pop')
398          this.tool.initSwiperHandler($dom,{
399            loop: true,
400            autoplay: {
401              delay: 3000,
402              disableOnInteraction: false
403            },
404            pagination: {el: '.swiper-pagination_how',clickable :true},
405            on:{
406              slideChange: function () {
407                let n = this.activeIndex
408                if (n > 5) n = 1
409                if (n < 1) n = 5                
410                _self.currentSwiperIndex = n
411              }
412            }
413          },'how_swiper')
414        },
415        dropdownClick(e,v,t) {
416          // 主要业务逻辑
417          if (t === 'index') {
418            switch(v) {
419              case 'withdrawal':
420                if (!this.accountInfo.withdrawal_config)
421                  this.tool.showTips('Please contact customer service for cash withdrawal', 'warn')
422                else {
423                  if (this.accountInfo.withdrawal) this.goWithdrawal()
424                  else this.tool.showTips(this.accountInfo.income_commission > 0 ? 'The number of withdrawals on the day has been capped' : 'There is no amount to withdraw','warn')
425                }
426                break
427              case 'income_details':
428                this.thisView = 'commission_details'
429                this.commissionView = 'index'
430                this.commissionTab = 1
431                this.toView(this.thisView,'btn')
432                break
433            }
434          } else if (t === 'traffic' || t === 'order') {
435            this[`report_${t}_date_type`] = v
436            this.report_type = t
437            this.getReportSummary()
438          }
439          
440          // 处理下拉
441          const parent = e.target.parentNode
442          parent.classList.add('d-none')
443          setTimeout(() => {
444            parent.classList.remove('d-none')
445          }, 500)
446        },
447        toViewInfo() {
448          window.location.href = globalThis.Server.getRinseHref('/user.html#info', window.app.info.site)
449        }
450      }
451    }
452  }
453  /** 提现数据 */
454  get withdrawalData() {
455    const _that = this
456    return {
457      data:{
458        // 提现模块
459        withdrawType:'paypal', // 提现类型 paypal、bank
460        formPattern: {
461          name: '^\\S{3, 9}',
462          email: '^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$',
463          password: '(?=.*([a-zA-Z].*))(?=.*[0-9].*)[a-zA-Z0-9-*/+.~!@#$%^&*()]{6,20}$',
464          phone: '[0-9\\-]{1,30}',
465          number: '[0-9]+',
466          length: '^[\\s\\S]{1,30}$',
467          amount:'^[\\d\\.]+$'
468        },
469        payment_description:'',
470        paymentData: {PayPal:null,bank_transfer:null},
471        paypalLimit:{
472          draw_min_amount:20,
473          single_draw_max_amount:2000
474        },
475        bankLimit:{
476          draw_min_amount:300,
477          single_draw_max_amount:2000
478        },
479        // 发票
480        needInvoice: false,
481        temporaryInvoice: '',
482        // 地址
483        pluginsCountry: null,
484        multiple_address: []
485      },
486      methods: {
487        withdrawalInitData() {
488          this.withdrawType = 'paypal'
489          this.needInvoice = false
490          this.temporaryInvoice = ''
491        },
492        // 来到提现界面
493        async goWithdrawal() {
494          this.accountView = 'withdrawal'
495          const res = await this.api.doublePromise('getDistributeWithdrawalConfig',{site_id:this.site_id})
496          if (res.code === 0) {
497            this.payment_description = res.data.payment_description
498             const paypalInfo= (res.data.PayPal && res.data.PayPal.draw_min_amount !== '') ? res.data.PayPal : null
499            if (paypalInfo) {
500              this.paypalLimit.draw_min_amount = this.tool.priceFormat(paypalInfo.draw_min_amount)
501              this.paypalLimit.single_draw_max_amount = this.tool.priceFormat(paypalInfo.single_draw_max_amount)
502              delete paypalInfo.draw_min_amount
503              delete paypalInfo.single_draw_max_amount
504            }
505            this.paymentData.PayPal = paypalInfo
506
507            const bankInfo = (res.data.bank_transfer && res.data.bank_transfer.draw_min_amount !== '') ? res.data.bank_transfer : null
508            if (bankInfo) {
509              this.bankLimit.draw_min_amount = this.tool.priceFormat(bankInfo.draw_min_amount)
510              this.bankLimit.single_draw_max_amount = this.tool.priceFormat(bankInfo.single_draw_max_amount)
511              this.needInvoice = bankInfo.draw_invoice === 1
512              delete bankInfo.draw_min_amount
513              delete bankInfo.single_draw_max_amount
514            }
515            // 加载地址下拉组件
516            if ((!paypalInfo) && bankInfo) {
517              this.withdrawType = 'bank'
518              this.initAddressSelect()
519            } 
520            
521            this.paymentData.bank_transfer = bankInfo
522
523          }
524        },
525        // 获取文件
526        async changeInvoiceFile(e) {
527          const file = e.target.files[0]
528          const fileValid = await this.checkFileInfo(file)
529          if (fileValid) {
530            this.temporaryInvoice = file
531          } else {
532            this.temporaryInvoice ? console.log('stay before file') : e.target.value = ''
533          }
534        },
535        // 校验文件格式 size 单位mb
536        checkFileInfo(file = '', typeList = 'doc,docx,pdf,png,jpeg,jpg',size = 2) {
537          return new Promise(resolve => {
538            if (!file) resolve(false)
539            // 限制格式
540            if (typeList) {
541              const fileType = file.name.split('.')[file.name.split('.').length - 1]
542              if (!typeList.includes(fileType)) {
543                this.tool.showTips(`Only DOC,DOCX,PDF,PNG,JPEG and JPG files can be uploaded`,'warn')
544                resolve(false)
545              }
546            }
547
548            if (size) {
549              const limitSize = 1024 * 1024 * size
550              if (file.size > limitSize) {
551                this.tool.showTips(`The file size cannot exceed ${size}MB`,'warn')
552                resolve(false)
553              }
554            }
555            if (file.name.length > 100) {
556              this.tool.showTips(`The file name cannot exceed 100 characters`,'warn')
557              resolve(false)
558            }
559            resolve(true)
560          })
561        },
562        // 提交文件上传
563        async commitInvoiceFile() {
564          return new Promise(async resolve => {
565            const files = await this.uploadFile([this.temporaryInvoice])
566            if (files.length) {
567              this.paymentData.bank_transfer.upload_invoice = files[0]
568              resolve(true)
569            } else {
570              this.tool.showTips(`Please upload the invoice file`,'warn')
571              resolve(false)
572            }
573          })
574        },
575        // 文件上传
576        uploadFile(files) {
577          return new Promise(resolve => {
578            _that.utilts.uploadFile([...files])
579            .then(fileList => {
580              const list = fileList.map(item => item.host + '/' + item.cname)
581              resolve(list)
582            }).catch(err => {
583              this.tool.showTips(err.msg || err || 'Failed to upload files.','error')
584              resolve([])
585            })
586          })
587        },
588        // 切换支付方式
589        changeWithdrawType(e) {
590          if (e.target.value === 'bank') this.initAddressSelect()
591        },
592        // 地址下拉
593        async initAddressSelect() {
594          // 初始化国家列表
595          if (this.multiple_address.length === 0) await this.getCountryList()
596          if (!window.PluginSelector) await  new Load('/assets/plugins/selector.js')
597          this.initCountrySelect()
598        },
599        /**获取国家列表 */
600        async getCountryList() {
601          return new Promise(async resolve => {
602            const res = await this.api.doublePromise('getCountryList',{})
603            if (res.code === 0) this.$set(this, 'multiple_address', res.data)
604            resolve()
605          })
606        },
607        // 国家下拉插件
608        initCountrySelect() {
609
610          const $country = this.$refs['countrySelectBox']
611          if (!$country) return
612
613          const option = this.multiple_address.map(item => {
614            return { name: item.en_name, value: item.id }
615          })
616
617          if (this.pluginsCountry) {
618            this.pluginsCountry.clearValue()
619            this.pluginsCountry.destory()
620            this.pluginsCountry = null
621          }
622
623          const that = this
624          this.pluginsCountry = new PluginSelector({
625            target: $country, require: true, option, placeholder: _that.$t('Please select your country'), confirmTip: _that.$t('the content can not be blank'), onChange: res => {
626              that.paymentData.bank_transfer.country = res.value
627            }
628          })
629          this.pluginsCountry.init()
630        },
631        // 申请提现
632        async applyForWithdrawal(param) {
633          const res = await this.api.doublePromise('getDistributeWithdrawalCreate',param)
634          if (res.code === 0) {
635            new Modal().confirm(this.payment_description || _that.$t('Thank y
635ou for trying'), _that.$t('Withdrawal success'), { cancelText: _that.$t('Continue'), submitText: _that.$t('views') })
636            .then(async() => {
637              this.toView('commission_details')
638            }).catch(err=> {})
639            setTimeout(() => this.getAccountInfo(true), 200)
640          }
641        },
642        // 提现
643        async commitWithdrawal() {
644          const type = this.withdrawType
645          // 表单校验
646          const ev = document.getElementById(type === 'paypal' ? 'paypalForm' : 'bankForm')
647          ev.classList.add("was-validated")
648          if (ev.checkValidity() === false) return
649
650          if (type === 'paypal') {
651            const param = {
652              site_id:this.site_id,
653              withdraw_method:1,
654              ...this.paymentData.PayPal
655            }
656            this.applyForWithdrawal(param)
657          } else {
658            // 判断发票并获取发票文件
659            if (this.needInvoice) {
660              const invoice = await this.commitInvoiceFile()
661              if (!invoice) return
662            }
663            const param = {
664              site_id:this.site_id,
665              withdraw_method:2,
666              ...this.paymentData.bank_transfer
667            }
668            this.applyForWithdrawal(param)
669          }
670        }
671      }
672    }
673  }
674  /** 佣金详情 */
675  get commissionData() {
676    const _that = this
677    return {
678      data: {
679        commissionView:'index', // index、income_details
680        commissionTab:0,
681        wd_start_time:'',
682        wd_end_time:'',
683        withdrawalStatus:'',
684        withdrawalStatusList: [
685          {label:_that.$t('all'),value:''},
686          {label:_that.$t('Processing'),value:1},
687          {label:_that.$t('Remittance'),value:2},
688          {label:_that.$t('Completed'),value:3},
689          {label:_that.$t('Refuse'),value:4},
690          {label:_that.$t('Cancelled'),value:5}
691        ],
692        withdrawalList:[],
693        withdrawalMethod:{
694          1:_that.$t('Paypal'),
695          2: _that.$t('Bank Transfer')
696        },
697        // 佣金
698        dc_start_time: '',
699        dc_end_time: '',
700        commissionForm: '',
701        commissionFormList: [
702          {label:_that.$t('all'),value:''},
703          {label:_that.$t('Income'),value:1},
704          {label:_that.$t('Expense'),value:2}
705        ],
706        commissionList:[],
707        // 提现详情
708        withdrawalDetail:{content:{}}
709      },
710      methods:{
711        loadCommissionApi() {
712          return new Promise(async resolve => {
713            
714            if (this.commissionTab === 0) {
715              await this.getDistributeWithdrawalMyList()
716            } else {
717              await this.getDistributeMemberCommissionList()
718            }
719
720            resolve()
721          })
722        },
723        // 切换tab标签
724        changeCommissionTab(v) {
725          this.pagingInitData()
726          this.commissionDetailInitData()
727          this.commissionTab  = v
728          if (v === 0) {
729            this.getDistributeWithdrawalMyList()
730          } else {
731            this.getDistributeMemberCommissionList()
732          }
733        },
734        // 初始化参数
735        commissionDetailInitData() {
736
737          this.wd_start_time = ''
738          this.wd_end_time = ''
739          this.withdrawalStatus = ''
740          this.withdrawalList = []
741
742          this.dc_start_time = ''
743          this.dc_end_time = ''
744          this.commissionForm = ''
745          this.commissionList = []
746
747        },
748        // 修改参数
749        changeCommissionParam() {
750          this.pagingInitData()
751          const v = this.commissionTab
752          if (v === 0) {
753            this.getDistributeWithdrawalMyList()
754          } else {
755            this.getDistributeMemberCommissionList()
756          }
757        },
758        // 取消某个提现
759        cancelWithdrawal(id,index) {
760          new Modal().confirm(_that.$t('Are you sure to cancel this withdrawal?'), _that.$t('Tips'), { cancelText: _that.$t('Back'), submitText: _that.$t('Yes') })
761          .then(async() => {
762            const res = await this.api.doublePromise('getDistributeWithdrawalCancel',{site_id:this.site_id,id})
763            if (res.code === 0) {
764              if (index === 'detail') {
765                this.lookWithdrawalDetail(id)
766                this.getDistributeWithdrawalMyList()
767              } else {
768                this.$set(this.withdrawalList[index],'status',5)
769                this.$set(this.withdrawalList[index],'status_format','Cancelled')
770              }
771              this.tool.showTips('Cancel the success')
772            }
773          }).catch(() => {})
774        },
775        // 查看提现详情
776        async lookWithdrawalDetail(id) {
777          this.commissionView = 'income_details'
778          this.withdrawalDetail = {content:{}}
779          const res = await this.api.doublePromise('getDistributeWithdrawalDetail',{site_id:this.site_id,id})
780          if (res.code === 0) {
781            const info = res.data
782            info.method_format = this.withdrawalMethod[info.method] || _that.$t('Other')
783            let s_f = this.withdrawalStatusList.find(e => e.value === info.status)
784            info.status_format = s_f && s_f.label || '--'
785            this.withdrawalDetail = info
786          }
787        },
788        // 提现记录
789        getDistributeWithdrawalMyList() {
790          return new Promise(async resolve => {
791            if (!this.tool.compareTime(this.wd_start_time,this.wd_end_time)) {
792              [this.wd_start_time,this.wd_end_time] = [this.wd_end_time, this.wd_start_time]
793            }
794            const param = {
795              site_id: this.site_id,
796              start_time: this.tool.dateAddTime(this.wd_start_time),
797              end_time: this.tool.dateAddTime(this.wd_end_time, 'end'),
798              status: this.withdrawalStatus,
799              sort: '',
800              page_number: this.page_number,
801              page_size: this.page_size
802            }
803            const res = await this.api.doublePromise('getDistributeWithdrawalMyList',param)
804            if (res.code === 0) {
805              const list = res.data.list || []
806              list.forEach(item => {
807                let s_f = this.withdrawalStatusList.find(e => e.value === item.status)
808                item.status_format = s_f && s_f.label || '--'
809                item.method_format = this.withdrawalMethod[item.method] || _that.$t('Other')
810              })
811              this.withdrawalList = list
812              this.total = res.data.total
813              this.page_count = res.data.page_count
814            }
815            resolve()
816          })
817        },
818        // 佣金收支记录
819        getDistributeMemberCommissionList() {
820          return new Promise(async resolve => {
821            if (!this.tool.compareTime(this.dc_start_time,this.dc_end_time)) {
822              [this.dc_start_time,this.dc_end_time] = [this.dc_end_time, this.dc_start_time]
823            }
824            const param = {
825              start_time: this.tool.dateAddTime(this.dc_start_time),
826              end_time: this.tool.dateAddTime(this.dc_end_time, 'end'),
827              form: this.commissionForm,
828              page_number: this.page_number,
829              page_size: this.page_size
830            }
831            const res = await this.api.doublePromise('getDistributeMemberCommissionList',param)
832            if (res.code === 0) {
833              const list = res.data.list || []
834              list.forEach(item => {
835                let f_f = this.commissionFormList.find(e => e.value === item.form)
836                item.form_format = f_f && f_f.label || '--'
837              })
838              this.commissionList = list
839              this.total = res.data.total
840              this.page_count = res.data.page_count
841            }
842            resolve()
843          })
844        }
845      }
846    }
847  }
848  /** 消息数据 */
849  get messageData() {
850    const _that = this
851    return {
852      data: {
853        messageType:1, // 1消息 2常见问题 3教程,
854        currentMsgIndex: -1,
855        messageList:[]
856      },
857      methods:{
858        messageInitData() {
859          this.messageList = []
860          this.currentMsgIndex = -1
861        },
862        loadMessageApi() {
863          this.messageType = ['message','faq','tutorial'].indexOf(this.thisView) + 1
864          return new Promise(async resolve => {
865            const param = {
866              site_id:this.site_id,
867              type:this.messageType,
868              start_time: '',
869              end_time:'',
870              title:'',
871              status:1, //状态:-1-全部;0-下架;1-上架
872              page_size:this.page_size,
873              page_number:this.page_number
874            }
875            const res = await this.api.doublePromise('getMessageNoticeListPage',param)
876            if (res.code === 0) {
877              const list = res.data.list || []
878              list.forEach(item => item.detail = '')
879              this.messageList = list
880              this.total = res.data.total
881              this.page_count = res.data.page_count
882              this.currentMsgIndex = -1
883            }
884            resolve()
885          })
886        },
887        // 消息详情
888        async messageShutter(i) {
889          if (i === this.currentMsgIndex) {
890            this.currentMsgIndex = -1
891            return
892          }
893          // 已查过详情则直接展开
894          if (!this.messageList[i].detail) {
895            const param = {
896              site_id:this.site_id,
897              type:this.messageType,
898              id:this.messageList[i].id
899            }
900            const res = await this.api.doublePromise('getMessageNoticeShowDetail',param)
901            if (res.code === 0) {
902              this.messageList[i].detail = res.data.content
903            }
904          } 
905          
906          this.currentMsgIndex = i
907        }
908      }
909    }
910  }
911  /** 分享产品 */
912  get shareProductData() {
913    const _that = this
914    return {
915      data: {
916        shareType:'link',
917        shareProductList:[],
918        shareProductLink:'',
919        sp_min_price: '',
920        sp_max_price: '',
921        sp_category_list:[],
922        sp_category_id: 0,
923        sp_title:'',
924        sp_sort_list: [
925          {label:_that.$t('Most Popular'),value:'favorite'},
926          {label:_that.$t('New Arrival'),value:'show_time'}
927        ],
928        sp_sort: 'show_time',
929        // 下方为弹窗数据
930        showSharePop:false,
931        sharePop:'',
932        current_dt_product_id: ''
933      },
934      methods:{
935        loadShareProductApi() {
936          return new Promise(async resolve => {
937            const param = {
938              site_id:this.site_id,
939              product_category_id: this.sp_category_id,
940              min_price: this.sp_min_price,
941              max_price: this.sp_max_price,
942              title: this.sp_title,
943              sort:this.sp_sort,
944              page_size:12,
945              page_number:this.page_number
946            }
947            const res = await this.api.doublePromise('getDistributeProductShareList',param)
948            if (res.code === 0) {
949              const list = res.data.list || []
950              this.shareProductList = list
951              this.total = res.data.total
952              this.page_count = res.data.page_count
953            }
954            if (!this.sp_category_list.length) this.getCategoryList()
955            resolve()
956          })
957        },
958        shareProductInitData() {
959          this.shareProductList = []
960          this.shareProductLink = ''
961          this.sp_min_price =  ''
962          this.sp_max_price =  ''
963          this.sp_category_list = []
964          this.sp_category_id =  0
965          this.sp_title = ''
966          this.sp_sort =  'show_time'
967        },
968        async getCategoryList() {
969          const param = {
970            site_id:this.site_id
971          }
972          const res = await this.api.doublePromise('getProductTypeList',param)
973          if (res.code === 0) {
974            this.sp_category_list = res.data
975          }
976        },
977        changeShareProductParam() {
978          this.pagingInitData()
979          this.loadShareProductApi()
980        },
981        // 去分享
982        goShareProduct(thirdLink = '') {
983          // 记录点击次数
984          this.api.doublePromise('getDistributeProductRecordShare',{site_id:this.site_id,dt_product_id: this.current_dt_product_id})
985          if (thirdLink) {
986            let shareLink = ''
987            switch(thirdLink) {
988              case 'facebook': shareLink = 'https://www.facebook.com/sharer/sharer.php?u=' + this.shareProductLink; break ;
989              case 'pinterest': shareLink = 'https://pinterest.com/pin/create/button/?url=' + this.shareProductLink; break ;
990              case 'twitter': shareLink = 'https://twitter.com/intent/tweet?url=' + this.shareProductLink; break ;
991            }
992            if (shareLink) window.app.utilts.jupmLinkSave({ href: shareLink, target:'_blank', name:thirdLink })
993          } else {
994            this.tool.copyText(this.shareProductLink)
995            this.goSharePop(false)
996          }
997        },
998        // 分享产品点击后弹窗
999        goSharePop(flag = false,copyText = '',dt_product_id = '') {
1000          // 记录点击产品id
1001          if (flag) this.current_dt_product_id = dt_product_id
1002          this.shareProductLink = window.location.host + globalThis.Server.getRinseHref(copyText, window.app.info.site)
1003          this.showSharePop = flag
1004          let $pop = document.querySelector(`#${_that.attrId} .affiliate-share_pop`)
1005          const $app = document.querySelector('#app')
1006          let isFirst = true
1007          if (!$pop) {
1008            if (this.sharePop) $pop = this.sharePop
1009            else $pop = $app.querySelector('.affiliate-share_pop')
1010            isFirst = false
1011            if (!$pop) return
1012          }
1013          if (!this.sharePop && flag && isFirst) $app.appendChild($pop)
1014          $pop.classList[flag ? 'remove' : 'add']('d-none')
1015          this.sharePop = $pop
1016        }
1017      }
1018    }
1019  }
1020  /** 订单报告 */
1021  get ordersReportData() {
1022    const _that = this
1023    return {
1024      data: {
1025        orderReportList:[],
1026        op_start_time:'',
1027        op_end_time:'',
1028        // 1-待付款;4-待发货;12-已发货;21-已完成;31-已取消;32-退款
1029        order_status_list:[
1030          {label:_that.$t('All Orders'),value:0},
1031          {label:_that.$t('Awaiting Payment'),value:1},
1032          {label:_that.$t('Awaiting Shipment'),value:4},
1033          {label:_that.$t('Shipping'),value:12},
1034          {label:_that.$t('Completed'),value:21},
1035          {label:_that.$t('Cancel'),value:31},
1036          {label:_that.$t('Refund'),value:32}
1037        ],
1038        op_order_status:0,
1039        // 0-待定;1-可提取;2-已取消
1040        commission_status_list:[
1041          {label:_that.$t('all'),value:-1},
1042          {label:_that.$t('Pending'),value:0},
1043          {label:_that.$t('Can Extract'),value:1},
1044          {label:_that.$t('Cancel'),value:2}
1045        ],
1046        op_commission_status:-1
1047      },
1048      methods:{
1049        loadOrdersReportApi() {
1050          return new Promise(async resolve => {
1051            if (!this.tool.compareTime(this.op_start_time,this.op_end_time)) {
1052              [this.op_start_time,this.op_end_time] = [this.op_end_time, this.op_start_time]
1053            }
1054            const param = {
1055              dt_member_id:this.accountInfo.id,
1056              site_id:this.site_id,
1057              start_time: this.tool.dateAddTime(this.op_start_time),
1058              end_time: this.tool.dateAddTime(this.op_end_time, 'end'),
1059              order_status: this.op_order_status,
1060              commission_status:this.op_commission_status,
1061              page_size:this.page_size,
1062              page_number:this.page_number
1063            }
1064            const res = await this.api.doublePromise('getDistributeMemberOrderList',param)
1065            if (res.code === 0) {
1066              const list = res.data.list || []
1067              list.forEach(item => {
1068                item.order_amount = this.moneyUnit + this.tool.numAddComma(item.order_amount,true)
1069                item.commission = this.moneyUnit + this.tool.numAddComma(item.commission,true)
1070                let o_s = this.order_status_list.find(e => e.value === item.order_status)
1071                item.order_status_format = o_s && o_s.label || '--'
1072                let c_s = this.commission_status_list.find(e => e.value === item.commission_status)
1073                item.commission_status_format = c_s && c_s.label || '--'
1074              })
1075              this.orderReportList = list
1076              this.total = res.data.total
1077              this.page_count = res.data.page_count
1078            }
1079            resolve()
1080          })
1081        },
1082        ordersReportInitData() {
1083          this.op_order_status = 0
1084          this.op_commission_status = -1
1085          this.orderReportList = []
1086          this.op_start_time = ''
1087          this.op_end_time = ''
1088        },
1089        // 参数更新
1090        changeOrdersReportParam() {
1091          this.pagingInitData()
1092          this.loadOrdersReportApi()
1093        }
1094      }
1095    }
1096  }
1097  /** 链接报告 */
1098  get LinksReportData() {
1099    const _that = this
1100    return {
1101      data: {
1102        lp_start_time:'',
1103        lp_end_time:'',
1104        linkReportList:[]
1105      },
1106      methods:{
1107        loadLinksReportApi() {
1108          return new Promise(async resolve => {
1109            if (!this.tool.compareTime(this.lp_start_time,this.lp_end_time)) {
1110              [this.lp_start_time,this.lp_end_time] = [this.lp_end_time, this.lp_start_time]
1111            }
1112            const param = {
1113              start_time: this.tool.dateAddTime(this.lp_start_time),
1114              end_time: this.tool.dateAddTime(this.lp_end_time, 'end'),
1115              page_size:this.page_size,
1116              page_number:this.page_number
1117            }
1118            const res = await this.api.doublePromise('getDistributeProductStatisticList',param)
1119            if (res.code === 0) {
1120              const list = res.data.list || []
1121              list.forEach(item => {
1122                item.order_amounts = this.moneyUnit + this.tool.numAddComma(item.order_amounts,true)
1123                item.pay_order_amounts = this.moneyUnit + this.tool.numAddComma(item.pay_order_amounts,true)
1124                item.pending_commission = this.moneyUnit + this.tool.numAddComma(item.pending_commission,true)
1125                item.active_commission = this.moneyUnit + this.tool.numAddComma(item.active_commission,true)
1126              })
1127              this.linkReportList = list
1128              this.total = res.data.total
1129              this.page_count = res.data.page_count
1130            }
1131            resolve()
1132          })
1133        },
1134        linksReportInitData() {
1135          this.lp_start_time = ''
1136          this.lp_end_time = ''
1137          this.linkReportList = ''
1138        },
1139        // 参数更新
1140        changeLinksReportParam() {
1141          this.pagingInitData()
1142          this.loadLinksReportApi()
1143        }
1144      }
1145    }
1146  }
1147  /** 促销报告 */
1148  get promotionReportData() {
1149    const _that = this
1150    return {
1151      data: {
1152        pp_start_time:'',
1153        pp_end_time:'',
1154        promotionReportList:[],
1155        promotionStatisticInfo: {
1156          share_product_total_clicks:0,
1157          orders:0,
1158          pending_commission:0,
1159          active_commission:0
1160        },
1161        promotionEcharts:{
1162          legendData:[_that.$t('Promotion Link Click Amount'), _that.$t('Promotion Order Count'), _that.$t('Pending Commission'), _that.$t('Active Commission')],
1163          xAxisData:[],
1164          seriesData:[
1165            {
1166              name: _that.$t('Promotion Link Click Amount'),
1167              type: 'line',
1168              data: []
1169            },
1170            {
1171              name: _that.$t('Promotion Order Count'),
1172              type: 'line',
1173              data: []
1174            },
1175            {
1176              name: _that.$t('Pending Commission'),
1177              type: 'line',
1178              data: []
1179            },
1180            {
1181              name: _that.$t('Active Commission'),
1182              type: 'line',
1183              data: []
1184            }
1185          ]
1186        }
1187      },
1188      methods:{
1189        async loadPromotionApi(){
1190          return new Promise(async resolve => {
1191            // 判断日期开始和结束是否合理,不合理则交换位置
1192            if (!this.tool.compareTime(this.pp_start_time,this.pp_end_time)) {
1193              [this.pp_start_time,this.pp_end_time] = [this.pp_end_time, this.pp_start_time]
1194            }
1195            if (this.tool.dateCompare(this.pp_start_time,this.pp_end_time) > 90) {
1196              this.tool.showTips('You can select a maximum of 90 days','warn')
1197              return
1198            }
1199            const param = {
1200              dt_member_id:this.accountInfo.id,
1201              site_id:this.site_id,
1202              start_time: this.tool.dateAddTime(this.pp_start_time),
1203              end_time: this.tool.dateAddTime(this.pp_end_time, 'end'),
1204              page_size:100,
1205              page_number:1
1206            }
1207            const res = await this.api.doublePromise('getDistributeMemberStatisticList',param)
1208            if (res.code === 0) {
1209              const list = res.data.list || []
1210              this.promotionEchartsDataInit()
1211              list.forEach(item => {
1212                // 统计
1213                for(let i in this.promotionStatisticInfo) {
1214                  this.promotionStatisticInfo[i] += item[i]
1215                }
1216                // 图表数据
1217                this.promotionEcharts.xAxisData.push(item.date_time)
1218                this.promotionEcharts.seriesData[0].data.push(item.share_product_total_clicks)
1219                this.promotionEcharts.seriesData[1].data.push(item.orders)
1220                this.promotionEcharts.seriesData[2].data.push(this.tool.priceFormat(item.pending_commission,2,true))
1221                this.promotionEcharts.seriesData[3].data.push(this.tool.priceFormat(item.active_commission,2,true))
1222                // 转换
1223                item.order_amounts = this.moneyUnit + this.tool.numAddComma(item.order_amounts,true)
1224                item.pay_order_amounts = this.moneyUnit + this.tool.numAddComma(item.pay_order_amounts,true)
1225                item.pending_commission = this.moneyUnit + this.tool.numAddComma(item.pending_commission,true)
1226                item.active_commission = this.moneyUnit + this.tool.numAddComma(item.active_commission,true)
1227              })
1228              this.promotionReportList = list
1229            }
1230            // 初始化图表,需要dom在显示状态才能初始化
1231            this.promotionEcharts.xAxisData.reverse()
1232            this.promotionEcharts.seriesData[0].data.reverse()
1233            this.promotionEcharts.seriesData[1].data.reverse()
1234            this.promotionEcharts.seriesData[2].data.reverse()
1235            this.promotionEcharts.seriesData[3].data.reverse()
1236            this.initPromotionEcharts()
1237            resolve()
1238          })
1239        },
1240        promotionReportInitData() {
1241          this.pp_start_time = this.mathChangeDate(this.formatDateThis(new Date(), '-', true), '-', 7, true)
1242          this.pp_end_time = this.formatDateThis(new Date(),'-', true)
1243          this.promotionReportList = ''
1244          // 从工具类里销毁图表实例
1245          this.tool.disposeEchartHandler('promotionEchartsEntity')
1246          this.promotionEchartsDataInit()
1247        },
1248        // 选择时间时联动计算7天周期
1249        changePromotionParamDate(e,type) {
1250          // if (type === 'start') {
1251          //   this.pp_end_time = this.mathChangeDate(e.target.value, '+', 7, true)
1252          // } else {
1253          //   this.pp_start_time = this.mathChangeDate(e.target.value, '-', 7, true)
1254          // }
1255        },
1256        // 加减时间
1257        mathChangeDate(date, method, days, flag) {
1258          // 时间戳转日期,falg:true表示只要年月日,part: year month date
1259          const toDate = (number, flag, part) => {
1260            let n = number
1261            let date = new Date(parseInt(n) * 1000)
1262            let y = date.getFullYear()
1263            let m = date.getMonth() + 1
1264            m = m < 10 ? ('0' + m) : m
1265            let d = date.getDate()
1266            d = d < 10 ? ('0' + d) : d
1267            let h = date.getHours()
1268            h = h < 10 ? ('0' + h) : h
1269            let minute = date.getMinutes()
1270            let second = date.getSeconds()
1271            minute = minute < 10 ? ('0' + minute) : minute
1272            second = second < 10 ? ('0' + second) : second
1273            if (flag) {
1274              if (part == 'year') {
1275                return y
1276              } else if (part == 'month') {
1277                return m
1278              } else if (part == 'date') {
1279                return n
1280              }
1281              return y + '-' + m + '-' + d
1282            }
1283            return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second
1284          }
1285          // method:'+' || '-'
1286          // ios不解析带'-'的日期格式,要转成'/',不然Nan,切记
1287          let dateVal = date.replace(/-/g, '/')
1288          let timestamp = Date.parse(dateVal)
1289          if (method == '+') {
1290            timestamp = timestamp / 1000 + 24 * 60 * 60 * days
1291          } else if (method == '-') {
1292            timestamp = timestamp / 1000 - 24 * 60 * 60 * days
1293          }
1294          return toDate(timestamp, flag)
1295        },
1296        // 获取当前时间, flag 表示只要年月日
1297        formatDateThis(date, lab = '-', flag) {
1298          // è¡¥0
1299          const formatNumber = n => {
1300            n = n.toString()
1301            return n[1] ? n : '0' + n
1302          }
1303          const year = date.getFullYear()
1304          const month = date.getMonth() + 1
1305          const day = date.getDate()
1306          const hour = date.getHours()
1307          const minute = date.getMinutes()
1308          const second = date.getSeconds()
1309          if (flag) return [year, month, day].map(formatNumber).join(lab)
1310          return [year, month, day].map(formatNumber).join(lab) + ' ' + [hour, minute, second].map(formatNumber).join(':')
1311        },
1312        promotionEchartsDataInit(){
1313          this.promotionStatisticInfo = {
1314            share_product_total_clicks:0,
1315            orders:0,
1316            pending_commission:0,
1317            active_commission:0
1318          }
1319          this.promotionEcharts.xAxisData = []
1320          this.promotionEcharts.seriesData[0].data = []
1321          this.promotionEcharts.seriesData[1].data = []
1322          this.promotionEcharts.seriesData[2].data = []
1323          this.promotionEcharts.seriesData[3].data = []
1324        },
1325        // 参数更新
1326        changePromotionReportParam() {
1327          this.pagingInitData()
1328          this.loadPromotionApi()
1329        },
1330        initPromotionEcharts() {
1331          const dom = document.querySelector('.promotion-echarts-box')
1332          if (!dom) return
1333          const option = {
1334            title: {
1335              text: ''
1336            },
1337            tooltip: {
1338              trigger: 'axis'
1339            },
1340            legend: {
1341              data: this.promotionEcharts.legendData,
1342              width: '70%',
1343            },
1344            grid: {
1345              left: '3%',
1346              right: '4%',
1347              bottom: '3%',
1348              containLabel: true
1349            },
1350            toolbox: {
1351              feature: {
1352                magicType: { type: ['line', 'bar'] },
1353                saveAsImage: {}
1354              }
1355            },
1356            xAxis: {
1357              type: 'category',
1358              boundaryGap: false,
1359              data: this.promotionEcharts.xAxisData,
1360              axisLabel: {
1361                padding:[0,10,0,0]
1362              }
1363            },
1364            yAxis: {
1365              type: 'value'
1366            },
1367            series: this.promotionEcharts.seriesData
1368          }
1369          this.tool.initEchartsHandler(dom,option,'promotionEchartsEntity')
1370        }
1371      }
1372    }
1373  }
1374  /** excel报表导出的处理 */
1375  get excelHandlerData() {
1376    const _that = this
1377    return {
1378      methods:{
1379        // 导出报表数据处理 v必传,不传会拿$event的值
1380        exportExcelHandler(v) {
1381          new Modal().confirm(_that.$t('export a report?'), _that.$t('Tips'), { cancelText: _that.$t('Cancel'), submitText: _that.$t('Confirm') })
1382          .then(async() => {
1383            const $v = v
1384            let exportList = []
1385            let excelHeader = ''
1386            let jsonKeys = []
1387            switch($v) {
1388              case 'orders_report': 
1389                excelHeader = 'order id,order amount,Date,order status,Commission,Commission Status'
1390                jsonKeys = ['serial_number','order_amount','order_time','order_status_format','commission','commission_status_format']
1391                exportList = this.tool.deepClone(this.orderReportList)
1392                break
1393              case 'links_report':
1394                excelHeader = `Product Name,Clicks,Order Count,order amount,Valid Orders,Valid Amount,Pending Commission,Active Commission`
1395                jsonKeys = ['product_title','share_product_clicks','orders','order_amounts','pay_orders','pay_order_amounts','pending_commission','active_commission']
1396                exportList = this.tool.deepClone(this.linkReportList)
1397                break
1398              case 'promotion_reports':
1399                excelHeader = `Date,Promoted link clicks,Promotion Order Count,Sales Amount,Effective Order Count,Effective Sale Amount,Pending Commission,Active Commission`
1400                jsonKeys = ['date_time','share_product_total_clicks','orders','order_amounts','pay_orders','pay_order_amounts','pending_commission','active_commission']
1401                exportList = this.tool.deepClone(this.promotionReportList)
1402                break
1403            }
1404            if (!exportList.length) {
1405              this.tool.showTips('There is no data to export','warn')
1406              return
1407            }
1408            // 翻译
1409            const excelHeaderMap = (excelHeader.split(',')).map(item => {
1410              let translateStr = _that.$t(item)
1411              if (item === 'order amount' && translateStr === 'order amount') translateStr = 'Order Amount'
1412              return translateStr
1413            })
1414            excelHeader = excelHeaderMap.join(',')
1415
1416            const jsonData = []
1417            exportList.forEach(item => {
1418              let obj = {}
1419              jsonKeys.forEach(e => obj[e] = item[e])
1420              jsonData.push(obj)
1421            })
1422            // 参数 三个 json数据,表头数据,文件名称
1423            this.tool.exportExcel(jsonData,excelHeader,$v + new Date().getTime())
1424            
1425          }).catch(() => {})
1426        }
1427      }
1428    }
1429  }
1430}
1431
1432// 常用工具方法
1433class ScriptCommonUtil {
1434  constructor() {
1435    this.utilts = Utilts.ins()
1436  }
1437  /** 单例模式 */
1438  static ins() {
1439    if (!this.instance) {
1440      return this.instance = new ScriptCommonUtil()
1441    }
1442    return this.instance
1443  }
1444  getUnixTime(dateStr) {
1445    let newstr = dateStr.replace(/-/g, '/')
1446    let date = new Date(newstr)
1447    let time_str = date.getTime().toString()
1448    return time_str.substring(0, 10)
1449  }
1450  // 判断两个日期时间相差多少天
1451  dateCompare(date1, date2) {
1452    if (!date1 || !date2) return 0
1453    let dayNum = 0
1454    const dateTimeStamp1 = this.getUnixTime(date1)
1455    const dateTimeStamp2 = this.getUnixTime(date2)
1456    if (dateTimeStamp1 > dateTimeStamp2) {
1457      dayNum = Math.floor((dateTimeStamp1 - dateTimeStamp2) / 86400)
1458    } else {
1459      dayNum = Math.floor((dateTimeStamp2 - dateTimeStamp1) / 86400)
1460    }
1461    return dayNum
1462  }
1463  // 比较两个时间大小(格式参考yyyy-mm-dd hh:mm:ss)
1464  compareTime(startTime, endTime) {
1465    if (!startTime || !endTime) return true
1466    // 结束时间大于开始时间就是true  , 反之则为 false
1467    let sn = this.getUnixTime(startTime) * 1
1468    let en = this.getUnixTime(endTime) * 1
1469    if (en > sn) {
1470      return true
1471    }
1472    return false
1473  }
1474  // 日期加上时间点
1475  dateAddTime(date, type = 'start') {
1476    if (!date) return date
1477    return type === 'start' ? date + ' 00:00:00' : date + ' 23:59:59'
1478  }
1479  // 深拷贝
1480  deepClone(obj){
1481    if(typeof obj !== "object" || obj == null){
1482        return obj
1483    }
1484    
1485    let result = obj instanceof Array ? [] : {}
1486    
1487    for(let key in obj){
1488        if(obj.hasOwnProperty(key)){
1489            result[key] = this.deepClone(obj[key])
1490        }
1491    }
1492    
1493    return result
1494    
1495  }
1496  // 转化
1497  priceFormat(val,n = 2,flag = false) {
1498    if (isNaN(val)) val = 0
1499    if (flag && val === 0) return 0
1500    let tempVal = val
1501    if (val < 0) tempVal = -tempVal
1502    const result = val < 0 ? '-' + ((tempVal / 100).toFixed(n)) : (tempVal / 100).toFixed(n)
1503    return parseFloat(result)
1504  }
1505  // 数值逗号隔开
1506  numAddComma(num,format = false) {
1507    if (isNaN(num)) num = 0
1508    if (format) num = (num / 100).toFixed(2)
1509    const res = num.toString().replace(/\d+/, n => { // 先提取整数部分
1510      return n.replace(/(\d)(?=(\d{3})+$)/g, $1 =>{
1511        return $1+","
1512      })
1513    })
1514    return res
1515  }
1516  // 复制内容
1517  copyText(text,tips = 'Copy successful') {
1518
1519    if (navigator.clipboard && navigator.clipboard.writeText) {
1520      navigator.clipboard.writeText(text).then(()=> {
1521        /* clipboard successfully set */
1522        this.showTips(tips)
1523      }, () => {
1524        /* clipboard write failed */
1525        this.showTips('Copy failed')
1526      })
1527    } else {
1528      const textarea = document.createElement("textarea");
1529      textarea.textContent = text
1530      // Prevent scrolling to bottom of page in MS Edge
1531      textarea.style.position = "fixed"
1532      textarea.style.opacity = 0
1533      document.body.appendChild(textarea)
1534      textarea.select()
1535      try {
1536        // Security exception may be thrown by some browsers
1537        document.execCommand("copy")
1538        this.showTips(tips)
1539      } catch (ex) {
1540        console.warn("Copy to clipboard failed.", ex)
1541        this.showTips('Copy the failure')
1542      } finally {
1543        document.body.removeChild(textarea)
1544      }
1545    }
1546  }
1547  // 消息提示 type <info、warn、success、error>
1548  showTips(tip,type = 'success') {
1549    new Message()[type](window.app.utilts.$t(tip))
1550  }
1551  // 图表工具 , 这个实例其实是保存在这个工具类的
1552  disposeEchartHandler(echartEntity) {
1553    if (this[echartEntity]) this[echartEntity].dispose()
1554    this[echartEntity] = ''
1555  }
1556  async initEchartsHandler(dom, option, echartEntity) {
1557    if (!window.echarts) await new Load('/assets/plugins/echarts.min.js')
1558    if (!echarts || !dom || !echartEntity) return
1559    if (!this[echartEntity]) {
1560      this[echartEntity] = echarts.init(dom)
1561      window.addEventListener('resize',()=> {
1562        this[echartEntity].resize()
1563      })
1564    }
1565    this[echartEntity].showLoading('default')
1566    this[echartEntity].clear()
1567    this[echartEntity].setOption(option)
1568    this[echartEntity].hideLoading()
1569  }
1570  // swiper工具
1571  destroySwiperHandler(swiperEntity) {
1572    if (this[swiperEntity]) {
1573      this[swiperEntity].slideTo(0,0)
1574      this[swiperEntity].destroy()
1575      this[swiperEntity] = ''
1576    }
1577  }
1578  async initSwiperHandler(obj, config, swiperEntity) {
1579    if (!window.Swiper) await new Load('/assets/plugins/swiper.min.js')
1580    if (!this[swiperEntity]) this[swiperEntity] = new Swiper(obj, config)
1581    else this[swiperEntity].update()
1582  }
1583  // 
1584  // excel报表导出
1585  exportExcel(tabData, headData, excelName = 'test') {
1586    //要导出的json数据
1587    const jsonData = tabData || []
1588    //列标题,逗号隔开,每一个逗号就是隔开一个单元格
1589    let str = headData + '\n'
1590    //增加\t为了不让表格显示科学计数法或者其他格式
1591    for(let i = 0 ; i < jsonData.length ; i++ ){
1592      for(let item in jsonData[i]){
1593          str+=`"${jsonData[i][item] + '\t'}",`
1594      }
1595      str+='\n'
1596    }
1597    //encodeURIComponent解决中文乱码
1598    const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(str)
1599    //通过创建a标签实现
1600    let link = document.createElement("a")
1601    link.href = uri
1602    //对下载的文件命名
1603    link.download =  `${excelName}.csv`
1604    document.body.appendChild(link)
1605    link.click()
1606    document.body.removeChild(link)
1607    this.showTips('Export successful')
1608  }
1609}
1610// api接口
1611class ScriptAffiliateApi {
1612  constructor() {
1613    this.utilts = Utilts.ins()
1614    this.tool = ScriptCommonUtil.ins()
1615  }
1616  /** 单例模式 */
1617  static ins() {
1618    if (!this.instance) {
1619      return this.instance = new ScriptAffiliateApi()
1620    }
1621    return this.instance
1622  }
1623  // 二次封装的promise(解决await捕获问题)
1624  async doublePromise(funName,params = {},showTip = true) {
1625    return new Promise(resolve => {
1626      this[funName](params).then(res => {
1627        if (res.code !== 0 && showTip) {
1628          console.error('error=>',res.msg)
1629          this.tool.showTips(res.msg,'error')
1630        }
1631        resolve(res)
1632      }).catch(err => {
1633        const msg = err.msg || err
1634        console.error('error=>', msg)
1635        if (showTip) this.tool.showTips(msg,'error')
1636        resolve({code:-1,msg})
1637      })
1638    })
1639  }
1640  /** 分销员状态 */
1641  getDistributeMemberStatus(params) {
1642    return new Promise((resolve, reject) => {
1643      this.utilts.request({
1644        url: '/distribute-member/status',
1645        method: 'GET',
1646        params
1647      }).then(res => resolve(res))
1648      .catch(err => reject(err))
1649    })
1650  }
1651  /** 分销员信息 */
1652  getDistributeMemberInfo(params) {
1653    return new Promise((resolve, reject) => {
1654      this.utilts.request({
1655        url: '/distribute-member/info',
1656        method: 'GET',
1657        params
1658      }).then(res => resolve(res))
1659      .catch(err => reject(err))
1660    })
1661  }
1662  /** 分销报告 */
1663  getDistributeMemberReportSummary(params) {
1664    return new Promise((resolve, reject) => {
1665      this.utilts.request({
1666        url: '/distribute-member/report-summary',
1667        method: 'GET',
1668        params
1669      }).then(res => resolve(res))
1670      .catch(err => reject(err))
1671    })
1672  }
1673  /** 分享产品分页列表 */
1674  getDistributeProductShareList(params) {
1675    return new Promise((resolve, reject) => {
1676      this.utilts.request({
1677        url: '/distribute-product/share-list',
1678        method: 'GET',
1679        params
1680      }).then(res => resolve(res))
1681      .catch(err => reject(err))
1682    })
1683  }
1684  /** 记录产品分享 */
1685  getDistributeProductRecordShare(params) {
1686    return new Promise((resolve, reject) => {
1687      this.utilts.request({
1688        url: '/distribute-product/record-share',
1689        method: 'GET',
1690        params
1691      }).then(res => resolve(res))
1692      .catch(err => reject(err))
1693    })
1694  }
1695  /** 产品分类列表 */
1696  getProductTypeList(params) {
1697    return new Promise((resolve, reject) => {
1698      this.utilts.request({
1699        url: '/distribute-product/product-category',
1700        method: 'GET',
1701        params
1702      }).then(res => resolve(res))
1703      .catch(err => reject(err))
1704    })
1705  }
1706  /** 消息列表 */
1707  getMessageNoticeListPage(params) {
1708    return new Promise((resolve, reject) => {
1709      this.utilts.request({
1710        url: '/message-notice/list-page',
1711        method: 'GET',
1712        params
1713      }).then(res => resolve(res))
1714      .catch(err => reject(err))
1715    })
1716  }
1717  /** 消息详情 */
1718  getMessageNoticeShowDetail(params) {
1719    return new Promise((resolve, reject) => {
1720      this.utilts.request({
1721        url: '/message-notice/show-detail',
1722        method: 'GET',
1723        params
1724      }).then(res => resolve(res))
1725      .catch(err => reject(err))
1726    })
1727  }
1728  /** 订单报告列表 */
1729  getDistributeMemberOrderList(params) {
1730    return new Promise((resolve, reject) => {
1731      this.utilts.request({
1732        url: '/distribute-member/order-list',
1733        method: 'GET',
1734        params
1735      }).then(res => resolve(res))
1736      .catch(err => reject(err))
1737    })
1738  }
1739  /** 链接报告列表 */
1740  getDistributeProductStatisticList(params) {
1741    return new Promise((resolve, reject) => {
1742      this.utilts.request({
1743        url: '/distribute-product/statistic-list',
1744        method: 'GET',
1745        params
1746      }).then(res => resolve(res))
1747      .catch(err => reject(err))
1748    })
1749  }
1750  /** 促销报告列表 */
1751  getDistributeMemberStatisticList(params) {
1752    return new Promise((resolve, reject) => {
1753      this.utilts.request({
1754        url: '/distribute-member/statistic-list',
1755        method: 'GET',
1756        params
1757      }).then(res => resolve(res))
1758      .catch(err => reject(err))
1759    })
1760  }
1761  /** 提现记录列表 */
1762  getDistributeWithdrawalMyList(params) {
1763    return new Promise((resolve, reject) => {
1764      this.utilts.request({
1765        url: '/distribute-withdrawal/my-list',
1766        method: 'GET',
1767        params
1768      }).then(res => resolve(res))
1769      .catch(err => reject(err))
1770    })
1771  }
1772  /** 佣金记录列表 */
1773  getDistributeMemberCommissionList(params) {
1774    return new Promise((resolve, reject) => {
1775      this.utilts.request({
1776        url: '/distribute-member/commission-list',
1777        method: 'GET',
1778        params
1779      }).then(res => resolve(res))
1780      .catch(err => reject(err))
1781    })
1782  }
1783  /** 提现详情 */
1784  getDistributeWithdrawalDetail(params) {
1785    return new Promise((resolve, reject) => {
1786      this.utilts.request({
1787        url: '/distribute-withdrawal/detail',
1788        method: 'GET',
1789        params
1790      }).then(res => resolve(res))
1791      .catch(err => reject(err))
1792    })
1793  }
1794  /** 取消提现 */
1795  getDistributeWithdrawalCancel(params) {
1796    return new Promise((resolve, reject) => {
1797      this.utilts.request({
1798        url: '/distribute-withdrawal/cancel',
1799        method: 'POST',
1800        params
1801      }).then(res => resolve(res))
1802      .catch(err => reject(err))
1803    })
1804  }
1805  /** 提现配置 */
1806  getDistributeWithdrawalConfig(params) {
1807    return new Promise((resolve, reject) => {
1808      this.utilts.request({
1809        url: '/distribute-withdrawal/config',
1810        method: 'GET',
1811        params
1812      }).then(res => resolve(res))
1813      .catch(err => reject(err))
1814    })
1815  }
1816  /** 提现申请 */
1817  getDistributeWithdrawalCreate(params) {
1818    return new Promise((resolve, reject) => {
1819      this.utilts.request({
1820        url: '/distribute-withdrawal/create',
1821        method: 'POST',
1822        params
1823      }).then(res => resolve(res))
1824      .catch(err => reject(err))
1825    })
1826  }
1827  /**获取国家列表 */
1828  getCountryList() {
1829    return new Promise((resolve, reject) => {
1830      this.utilts.request({
1831        url: '/country/list-child',
1832        method: 'GET',
1833      }).then(res => resolve(res))
1834      .catch(err => reject(err))
1835    })
1836  }
1837  /** 分销页面设计 */
1838  getDistributeConfigDesignDetail(params) {
1839    return new Promise((resolve, reject) => {
1840      this.utilts.request({
1841        url: '/distribute-config/design-detail',
1842        method: 'GET',
1843        params
1844      }).then(res => resolve(res))
1845      .catch(err => reject(err))
1846    })
1847  }
1848}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.