推广管理系统开发过程总结

行云流水
2022-09-03 / 0 评论 / 203 阅读 / 正在检测是否收录...

前言

业务系统有一个分享返现的活动。用户在知乎或者小红书发表一篇使用心得,然后申请返现。已经支付的订单就会返还。原先订单少的时候,都是手动处理。随着订单量的增加,申请返现的也越来越多。有点处理不过来,同时已经返现的订单,有多少也不知道。于是有开发一个推广管理系统的想法,花一周时间实现了。特此记录实现过程,一切从简能用就好。

设计思路

photo模块

模型设计

#文章级别
# 关键词
A =  0
B =  1
C =  2
D =  3
E =  4

#来源
SRC_CHOICE = {
    A: '知乎',
    B: '小红书',
}

#文章级别
LEVEL_CHOICE = {
    A: '审核中',
    B: '未通过',
    C: '普通',
    D: '精品',
    E: '被删除',
}

# Create your models here.
class Article(models.Model):
    '''
    图鲁班文章模型类
    '''
    id = models.AutoField(primary_key=True)
    src_choices = ((k, v) for k,v in SRC_CHOICE.items())
    level_choices = ((k, v) for k,v in LEVEL_CHOICE.items())
    sno = models.CharField(max_length=32, verbose_name='编号', default='')
    title = models.CharField(max_length=255, verbose_name='标题', default='')
    url   = models.CharField(max_length=255, verbose_name='链接', default='')
    uid   = models.IntegerField(default=1, verbose_name='用户id')
    addtime = models.DateTimeField(auto_now_add=True, verbose_name= '添加时间')
    stype = models.SmallIntegerField(default='1', choices=src_choices, verbose_name='平台')
    slevel = models.SmallIntegerField(default='0', choices=level_choices, verbose_name='级别')
    note = models.CharField(max_length=1024, default='无', verbose_name='备注')

    def __str__(self):
        return self.sno

    class Meta:
        db_table = 'photo_article'
        verbose_name = '推广记录'
        verbose_name_plural = '推广记录'
code here...

后台展示自定义

# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
    #后台展示字段
    list_display = ['sno', 'show_firm_url', 'slevel', 'stype', 'addtime', 'repay_info', 'show_kefu', 'note']

    #过滤字段
    list_filter =  ["slevel", "stype"]

    #搜索字段
    search_fields = ['title']

    #只读字段
    readonly_fields = ['sno', 'uid', 'addtime']

    @admin.display(description='返现信息', ordering='')
    def repay_info(self, obj):
        num = 0  #条数
        w_p = 0  #未结算金额
        y_p = 0  #已结算金额

        repays = Repay.objects.filter(sno=obj.sno).all()
        if repays:
            for repay in repays:
                num = num + 1
                if repay.status == 0:
                    w_p = w_p + repay.price
                if repay.status == 1:
                    y_p = y_p + repay.price

        data = {'name':'返现记录', 'url':'/admin/photo/repay/?q={}'.format(obj.sno)}
        return format_html("<a href='javascript:;' onclick='self.parent.app.openTab({data})'>共{n}条, 已结算: {y}, 未结算: {w}</a>", data=data, n=num, y=y_p, w=w_p)

    #标题带链接
    @admin.display(description='标题', ordering='')
    def show_firm_url(self, obj):
        return format_html("<a href='{url}' target='_blank'>{title}</a>", url=obj.url, title=obj.title)

    #客服回复提示
    @admin.display(description='客服回复', ordering='')
    def show_kefu(self, obj):
        text = '您的返现申请已提交,结果可通过(http://tg.tuluban.top)自助查询。查询码:{}'.format(obj.sno)
        return format_html(f"""
                    <input type="text" id="{obj.id}" value="{text}" style="position: absolute; top: -10000px">
                    <a href="#" onclick="document.getElementById('{obj.id}').select(); document.execCommand('copy')">提示</a>
                    """)


    #隐藏不需要编辑的字段
    def get_form(self, request, obj=None, **kwargs):
        self.exclude = ('sno', 'uid', 'addtime')
        form = super(ArticleAdmin, self).get_form(request, obj, **kwargs)
        return form

    #重写保存函数
    def save_model(self, request, obj, form, change):
        #新增
        if not change:
            obj.uid = request.user.id
            obj.sno = datetime.now().strftime('%Y%m%d%H%M%S') + ''.join(str(i) for i in random.sample(range(0,9),4))

        repay = Repay.objects.filter(sno=obj.sno).filter(status=0)

        if obj.slevel == 2:
            if repay:
                repay.update(price=290)
            else:
                repay = Repay()
                repay.sno = obj.sno
                repay.price = 290
                repay.uid = obj.uid
                repay.note = obj.note
                repay.save()
        elif obj.slevel == 3:
            if repay:
                repay.update(price=490)
            else:
                repay = Repay()
                repay.sno = obj.sno
                repay.price = 490
                repay.uid = obj.uid
                repay.note = obj.note
                repay.save()

        #保存
        super(ArticleAdmin, self).save_model(request, obj, form, change)

新增订单接口

def photo_add(request):
    #定义返回字典
    resp = {}
    #获取请求参数
    if request.method == 'GET':
        u = request.GET.get('u', default=False)
        n =  request.GET.get('n', default='xwzy1130')
    else:
        u  = False

    if not u:
        resp['msg'] = '参数非法,提交失败!'
    else:
        data = get_info_by_url(u)
        if data:
            art = Article()
            art.sno = datetime.now().strftime('%Y%m%d%H%M%S') + ''.join(str(i) for i in random.sample(range(0,9),4))
            art.title = data[0]
            art.url = u
            art.stype = data[1]
            payinfo = PayInfo.objects.filter(username=n).last()
            if payinfo:
                art.uid = payinfo.uid
            else:
                art.uid = 1
                art.note = n
            art.save()
            resp['msg'] = '更新成功!查询码:{}'.format(art.sno)
        else:
            resp['msg'] = '提交失败!'
    return JsonResponse(resp)

frontend模块

view模版

#搜索结果页
def search_view(request,*args, **kwargs):
    return  render(request, 'frontend/search.html')

#自助提交页
def submit_view(request,*args, **kwargs):
    return  render(request, 'frontend/submit.html')

submit.html

 $(function () {
        // 搜索时执行ajax 查询匹配的数据 返回到list
        $(".handIpt").click(function () {
            var username = $("#username").val();
            var url = $("#url").val();
            if (isValidURL(url) && url.trim()) {
                $.ajax({
                    type: "GET",
                    url: "/photo/add?u=" + url + "&n=" + username,
                    dataType: "json",
                    success: function (data) {
                        alert(data.msg);
                    },
                    //打印错误
                    error:function(jqXHR,textStatus,errorThrown){
                        console.log(jqXHR);
                        console.log(textStatus);
                        console.log(errorThrown);
                    }
                });
            } else {
                alert("请检查推广链接!");
            }
        });

其他细节

js校验url是否合法

  function isValidURL(str_url) {
        var strRegex = "^((https|http|ftp|rtsp|mms)?://)"
  + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //ftp的user@
        + "(([0-9]{1,3}.){3}[0-9]{1,3}" // IP形式的URL- 199.194.52.184
        + "|" // 允许IP和DOMAIN(域名)
        + "([0-9a-z_!~*'()-]+.)*" // 域名- www.
        + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]." // 二级域名
        + "[a-z]{2,6})" // first level domain- .com or .museum
        + "(:[0-9]{1,4})?" // 端口- :80
        + "((/?)|" // a slash isn't required if there is no file name
        + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
        var re=new RegExp(strRegex);
        //re.test()
        if (re.test(str_url)){
            return (true);
        }else{
            return (false);
        }
    }

js 转码url

 // var e_url = encodeURIComponent (list[i].url);
 function movieDetail (url) {
        console.log(url);
        window.location.href= decodeURIComponent(url);
    }

Django设置静态文件目录

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static')

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

simpleUI 设置默认首页

#simpleui配置
SIMPLEUI_HOME_PAGE = '/photo/index'

评论 (0)

取消
只有登录/注册用户才可评论