写程序难在什么地方?

关于程序员的话题,可能会有几个这样的关键字:找不到女朋友、加班狗、薪水高、屌丝、鄙视链、跳槽、改Bug……感觉更多的是自嘲吧!其实这些都不是事,今天我们来说说程序员为什么自称码农,最苦逼的地方在哪里?

如果说学习编程,是一件挺有意思的事情,那么能够写出自己的第一个小项目,会兴奋好一段时间,可是和其他工作类似,比如重复的事情做N遍,也会有厌烦的时刻。

假设一个程序,有30个选项,每个选项有是或者否2种可能性,测试所有可能性有2的30次方,有10亿之多。

1天有60*60*24=86400秒,如果每种可能性需要发费1秒钟测试,那么10亿需要34年,想想都觉得恐怖吧,更加恐怖的是在于,不止30个选项。

在知乎见过这么一个段子,说一个客人在饭店点餐,点了一份宫保鸡丁。假设把这个场景放在程序员的工作当中,会是这样的。

一、原始需求
服务员,给我来一份宫保鸡丁。

二、中途变更需求
厨师做到一半,突然跟服务员说:不要放肉。
服务员:不放肉怎么做啊?
客人:不放肉就行了,其他正常做。
服务员:好的,您稍等!

三、改动太大,部分重构需求
厨师:你大爷!我肉都已经回锅了
服务员:客户非要这么要求的嘛!你把肉挑出来,不就行了!
服务员:行你大爷!然后还是一点点把肉挑出来了。

四、低估改动成本
客人:服务员,菜里面可以给我加一点腐竹吗?
服务员:行,这个应该挺简单的。

五、新需求引入了新研发成本
厨师:你TMD,不知道腐竹得提前泡水吗?炒到一半,你才说?跟他说,想要吃腐竹,需要等半天。
服务员:啊你怎么不早说
厨师:早说你MLGB,我怎么知道他要往宫保鸡丁里面放入腐竹啊?

六、某一功能点摇摆不定
客人:服务员,还是把肉加回去吧!
服务员:您,刚才不是说不要肉吗?
客人:现在,又想要了
服务员:行!您稍等

七、甲方是大爷
厨师:怎么这么想日你?菜都炒过火了你让我放肉?还好,肉我没扔。
服务员:客户提的要求你日我干嘛?
厨师:你就不能拒绝他啊?
服务员:人家是客户嘛!

八、改动开始导致工期延迟
客人:服务员,服务员,怎么这么半天,还不上菜!
服务员:您稍等,我给您催催!

九、开发者请求重新排期
厨师:催你M催啊,腐竹没有泡好,我还得重新放油。

十、甲方催活
服务员:抱歉,加腐竹的话,还需要等半天,您别着急哈
客人:什么,还要等多久?我现在就要吃,你们能快点嘛?在不端上来我就撤单。
服务员:好,您稍等

十一、开发者开始和中间人PK
厨师:日你个仙人板板,这改来改去的,逗我吗?这么下去,我要死了

十二、因工期过长,再次改动需求
客人:服务员,这样吧,腐竹不要了,换成蒜薹就能快点了吧,对了,再加上一点番茄酱。

十三、频繁修改开始导致大量冗余
厨师:我日了狗啊,你TM不知道蒜薹也得掉水啊?还有你怎么让我往热菜里放番茄酱啊???
服务员:掉水总比腐竹强吧,番茄酱往里一倒不就行了吗?很难吗?
厨师:草!腐竹,我还得接着泡,万一这孙子又想要了呢?

十四、奇葩需求
客人:茄丁加了没有,我去其它饭店,可以加了茄丁的啊。
服务员:好好好,您稍等

十五、奇葩你也得做
厨师:去他大爷的,他吃的宫保鸡丁是村西头瞎子王老头炒的宫保鸡丁吗?宫保鸡丁里面放茄丁?
服务员:茄丁炒了扔里面不就行了吗?
厨师:那他妈的还叫菜吗?哪个系的?
服务员:客户要,你就炒了吧
厨师:麻痹,你顺便问问腐竹还要不要,这盆腐竹占地方,不要我就扔了啊

十六、黑暗前的最后黎明
“服务员,还要多久好啊”
“很快,很快…”
“再给我来一杯西瓜汁”
“好…”
“你再不好,我就走了啊,反正,还没有给钱”
“很快,很快”

十七、最终决战
10分钟后
“咦,我上次吃的不是这个味道啊?”
“从厨房杀出来的大厨:我TM就日了你的狗了…”

人物对照:
厨师:码农
客户:老板/甲方
服务员:客户经理、产品经理

现实中点菜当然不会出现这么啼笑皆非的情况,但项目开发中的一些主要矛盾,和上面的例子有很多神似的地方。所以如果有人问编程最难的在哪里,也许从来不是语言本身,而是业务逻辑、需求变更,还有就是项目的管理吧!比如一个项目管理者最头疼的应该是,团队里出现了一个水平很差的程序员,提交代码等同于提交了更多的BUG,诸如此类!

所以,听完上面的这些,如果你还觉得编程是有趣的并希望成为你的职业,那一定是你的真爱。

便宜点,我就会买吗,我应该在哪个平台选择购买相机?

写这篇文章之前,首先说说为啥写这篇文章!

原因:

1.参与到一个新的电商网站项目,准备要上线了,但怎么运营,团队思路却很混乱。
2.我想挑一部价位在6000多左右的单反,然后尝试几个平台比较价格。

电商平台数据比较与分析

选择搜索的关键字:相机型号+镜头焦距。这是影响相机价格的核心因素。当然后面你可以看到除此之外还包括是否带赠品、套餐之类的,先不看。

确定了搜索的关键词为:EOS 800D 18-135mm

  • 官方渠道:6699
  • 分销商渠道:6390~6588 (上下浮动198元) 备注:部分有提供延保、赠品的额外服务
  • 支持分期:费率在月0.5
  • 物流:大部分从北京发货

  • 官方:7199
  • 分销商渠道:6299~6800 (上下浮动500) 备注:天猫的价格波动取决于套餐搭配的物件(诸如:备用电池、三脚架、相机包配件等等)
  • 支持分期:费率在月0.5
  • 物流:广州、北京、上海

  • 分销商渠道:套餐价格 6358~6758 (上下浮动400)
  • 不支持分期
  • 物流:北京等

  • 官方:7099
  • 分销渠道:6749~6960 (上下浮动200左右)
  • 物流:2天
  • 支持信用卡、分期月0.5

整理数据如图:

根据数据图反馈,总结几点:

1.JD价格稳定,天猫套餐丰富价格浮动就较大,苏宁高不成低不就,亚马逊价格整体高于水平线。
2.天猫商家比较丰富(12月免息、套餐种类繁多)副作用是造成B2C的体验感略差,比较难以做出选择,销量大的卖家比较分散,这和天猫有广告系统有关(付费可以靠前)。
3.JD销量比较集中在几个有实力的大卖家身上,产品的排序没有广告的干扰。
4.物流方面:JD > 亚马逊 > 天猫

备注:本次数据仅以该单品为例。毕竟电子类产品算是JD的优势品类。

我到底该如何选择我的相机

任何数据分析最终的目的,是指导我们最终的决策。那么,这一篇幅我们要围绕,用户如何选择来进行阐述,价格因素是否重要呢?

文章的标题是:便宜点,我就会买吗?

所以,我们以价格作为本次阐述的主要出发点。因为这和最近我参与的一个项目有关系,价格是否应该作为一个新产品的卖点呢?它到底会起到什么样的作用,请拭目以待。

首先,我依据的点主要如下:

1.价格低很重要。因为任何好的产品一定是优于以往的产品,作为电商用户,价格是最敏感的,不能倒退。但价格低最大的问题会是是否是假货呢~所以官网渠道还是具有一定的吸引力的,这个应该是天猫的软肋之一,但可以肯定价格太低,肯定是不靠谱的。在天猫的运营里,同样的产品,价格越低也会获取到更好的流量(如果是这类薄利多销的产品类型,比较适合天猫平台)
2.平台也很重要。主要考虑:平台的品牌形象,作为电商以往的购物体验,比如:物流、支持分期、售后政策等;
3.APP\网站购买体验比较次要。电商的发展已经相对比较成熟,也是一个已经存在并且竞争激烈的市场,网站的购买体验感都已经比较成熟,这一点在平台之间没有体现出那么重要的地位。其他网站应该向这类成熟的平台靠齐即可!
4.平台的性质。我们知道天猫的盈利主要靠收取第三方卖家的交易手续的提成;JD包含自营和第三方入驻卖家,第三方入驻卖家丰富了产品的品类,但是有严格的审核机制,解放了JD的现金流。平台的提成应该相差不大,尤其是竞争激励的品类应该几乎没有什么差别。天猫全依靠第三方卖家,在产品的稳定性上是比不上JD的,这也是为什么JD一直以不卖假货作为品牌宣传,提到天猫的问题大部分也是会买到假货等;

那么,到底,我会做出什么样的选择,其实作为用户,选择天猫、JD都有自己的理由(抱歉,其他平台不用考虑在内了)。

用户群分析:

天猫:

1.大众消费者(更多套餐可以选择,而且确实有些商家,比起JD价格要低一点点,如果算上一堆赠品看上去非常划算,至于赠品质量的问题就不是我要考虑的问题);
2.对价格比较敏锐的用户(对产品比较了解的用户群体)。

京东:

1.大众消费者(对京东的电子类产品已经比较认可的消费者,过往的购买经历让其选择了京东;物流比较好,同城发货当天可收到货;价格比较稳定靠谱)

分析到这一步,结论应该是:电子类产品,我对价格的敏感度不高更多考虑是否稳定、安全,便宜点,我也不一定会买的。(忍住,迎接双12的到来,能省一点是一点,买到便宜的价格,这种成就感也是非常好的,这种感觉应该是从淘宝开始养成的)。

我会怎么买?电子类产品,尤其是大件的,可能首选JD。像风扇之类的,会去淘宝或者阿里巴巴,谁便宜就选择谁。服装类,会选择天猫类(因为笔者是男性的原因)。服装品类是天猫的一大优势,但是针对女性服装品类,主战场还有:唯品会、美丽说等。家居类会选择淘宝,这一品类感觉淘宝会经常有意想不到的惊喜,管他是不是仿货、比如仿外观等等呢。化妆品和饰品(买的比较少不做评论),针对女性市场,美妆品类网站还有:聚美、唯品会、网易考拉等。母婴类产品也算是一个大众消费品类(不做评论)。

电商,应该把价格作为卖点吗,不应该只是卖点!

国内的电商消费市场,几乎就是天猫、JD霸占。能够杀出重围的唯品会、聚美、考拉、社交电商类、母婴类基本上属于专注在细分领域的电商类型,可以想象电商行业的机会其实不多。

电商产品把价格作为卖点,是否合理呢?我的观点如下:价格是不可以作为卖点的,低是应该的,否则可能连关顾的用户都没有。这种价格低是以节约其他方面的成本来降低的价格,应该考虑的产品核心,其次也要考虑品牌的形象宣传。比如:流量获取的成本低、采购的成本低、复购率高、公司运营高效等等。但作为新兴的平台,并且是已存在市场分一杯羹,难度是竞争对手的N倍。毕竟降价是最简单、最粗暴的招数,任何人都可以降价,只存在是否降的起的问题(很显然,创业产品是不适合把价格低作为卖点的,而应该是降低成本的地方作为产品的核心优势)。

有产品意识的人,应该听过“痛点”。现有的产品无法满足用户的需求,能够把这一类“痛点”很好的解决的产品,才是比较有希望的,否则必将随着钱烧完了而完蛋。而解决“痛点”应该是每一个做产品的人应该敬畏的地方,它需要不断追求、勇于探索、试错。

做出1个产品,运营思路如果有问题,会影响很大,它不仅影响产品营销宣传的方向,也决定了产品开发方向。做产品也是没有办法偷懒的,而是逐步积累的,产品运营的任何一个问题,都有被无限放大的可能。何况,决定产品成败的因素可能很多很多,有的因素影响大,有些小而已罢了!所以JD能够成功也是有原因,以电子品类和家电为主、自建物流都成功的走在了天猫的前面,整体很稳健有自己的优势。

这个大叔不太冷
2017.12.1

创业型公司产品开发与客户探索的思路

「末尾有彩蛋」「末尾有彩蛋」「末尾有彩蛋」…..

本文结合工作经历以及《四步创业法》一书的观点进行阐述。也许,你也会成为那只“三眼乌鸦”,可以预测产品的未来。

我们要明白什么类型的公司是属于创业型公司。根据市场类型分三种:全新市场、现有市场、细分市场。创业型公司大多数应该属于细分市场。相比其他两类市场,全新市场成长周期过长失败率高、现有市场竞争激烈后入者难以撼动前者的市场地位。只有找到细分市场,这类市场属于现有产品无法更好的满足一些用户的需求而产生的市场,成功的概率要高,市场也是存在的。明白了创业型公司类型之后,创业型公司的产品,应该针对的是细分用户群的特殊需求。这里就不占用过多的篇幅来进行举例了,这样的案例是不胜枚举。

四步创业里,描述创业步骤是:「开发产品->市场检验->产品上线->组建公司」。这个步骤里,我们知道客户的探索(市场检验)是和开发产品紧密联系的,也是指导产品开发的重要依据。任何产品最初是从一个愿景的设想开始的。我们设想我们的产品可以解决那部分人群的需求、我们设想如何将产品推向市场、设想如何寻找意向客户、设想团队如何搭建。然后创业的过程只是不断的校验当初的设想,然后逐步的淘汰掉错误的设想,最终达成愿景的过程。

理解这个,和产品开发又有什么关联呢?作为产品开发人员,是这个创业链条里面的第一个步骤,也是产品本身的亲身构建者。作为和产品最亲密的接触者,这的确有着比市场人员更加敏锐的感受,产品的好坏可能你是最清楚的。当然基于分工的不同,市场开发人员所扮演的角色应该重点是给产品寻找天使用户。

重点来了,上面我们提到的是天使用户,而不是大众用户。为什么这么说呢?作为创业型的产品,最初可能只是想法、产品原型,还不适合面向大众用户。开发的思路不应该是满足大众的需求,而是满足核心用户(天使用户)的需求,最初阶段会为你的产品买单的天使用户才会成为你的客户,这部分客户因为没有更加适合的产品满足自己的需求。对于大众用户而言,目前这部分用户人群对你的产品提出的建议和需求,可能在这个阶段都是多余的,市场营销人员目前也不应该把大众用户的需求提交给产品开发人员。也许有人问了,难倒就不应该照顾大众用户了,这里要说的是,大众的需求并非这个阶段需要解决的核心问题。了解产品开发规律的用户,应该知道产品会有版本更新,产品应该是不断完善的。错误的把大众用户的需求,当做真实需求提交给产品部门,产品部门因为需求过多,也会导致产品的开发进度推迟,推迟发布也会导致市场拓展的推迟,夸张的说,如果产品开发需要1~2年变成1个完美的产品,可能也会失去了产品推向市场的最佳时间。而现实中,也经常出现一些产品在开发阶段,由于这也要做、那也要做,好像我们见过的功能,都希望自己的产品也有,仿佛那样,我们的产品就会披上神奇的外衣,而殊不知这将是一个错误的开始。

说远比做简单,最后以一个帖子《条件不充足(缺人缺钱缺资源),初创品牌怎么办?》作为本文的结尾。https://www.zhihu.com/question/21851271/answer/68591539

这个大叔不太冷 (有很多能力,正在消失,比如写作)

2017.11.30

IT工作之感悟篇

本篇仅以一名IT程序员的视角来阐述我的感悟,充满了比较理性的色彩。

总结一句话

IT工作,其实是不断的学习能力,通过反复的练习,在工作当中输出你的成果。

何为「输入」和「输出」。打一个比方,或许会更加容易理解。

作为一名销售,「输入」是学习产品的相关知识、收集相关的资料。「输出」是收集客户名单、分析客户信息、寻找目标客户对象、开始进行客户的沟通…省略N字…最终销售产品、维护客户。

通过这样一个例子,进一步理解「输入」与「输出」之间的关系,两者缺一不可。

回到工作中来讲,「输入」可以理解为,你对这份工作所需要学习的技能。「输出」可以理解为,你实际的工作付出。

理解了这些基本概念以后,我们对于IT工作的理解,实际上就是找到这种类型的工作的「输入」与「输出」了。

相比其他行业,IT工作的学习,也就是我们提到的输入,随着IT技术的变化飞快而变得输入也需要保持更新,否则你可能无法很好的输出,也就是无法更高效的开展你的工作,你的工作技能得到了退化。

至于,什么是IT工作的输出,想必不用做出过多的解释了。如果没有输出,等于没有给企业创造产出,作为一名IT程序员的产出,就是你的代码量,而且是有效的高质量的代码量。

说了,这么多,有人会问那么,我们应该如何做,才能更加有效了。

正确的方法如下,指定任务:每天学习并记录成文档,每周发布博客,每月完成一个项目示例,将代码进行开源、分享。比如,常见的视频学习,要坚持整理成文档,而不是一看而过,定期以项目的方式,来完成一个阶段的学习。IT工作其实和其他类型的工作一样,也需要反复训练,甚至需要付出更多的心血。

作者:这个大叔不太冷 (有很多能力,正在退化,比如写作!)

2017年11月25日

迷失

无论你相不相信,在人生的某些时刻你会处在一些谜团之中,有时你可以很快走出来,有时你却会迷路,而决定你尽快走出来的,只能是你自己…至少绝大多数的时候是这样的。

你所偶有期待的那些人、那些事也许就如同创业时的一些死胡同,或者如同开发中的伪需求,更多的只是人们臆想的存在,认真你就输了(不,应该是较真你就输了)。

到了人生的某个年龄,你也许会为虚度了年华而无比的懊悔、你也许会感叹逝去的那些人和事、你会认为这或许就是命运。

此刻,我对这一句话,突然之间有了更深的感悟。

有的人30岁就死了,70岁才埋。”

——这个大叔不太冷 2017.11

实用列表页, 弹出框, 图片上传JS整理

1. 全选/反选(Jquery实现)

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*HTML结构*/
<input type="checkbox" id="check_all">

<table class="table">
...
</table>

/*全选按钮*/
    $("#check_all").click(function () {
        if(this.checked) {
            $('.table :checkbox').prop("checked", true);
        } else {
            $('.table :checkbox').prop("checked", false);
        }
    })

2. 列表页提交:弹窗表单框,点击提交后自动关闭

第1步:添加按钮

Select Code
1
<a href="javascript:void(0)" class="btn btn-primary" onclick="add_edit_article(0)">添加文章</a>

第2步:添加按钮点击事件

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*添加文章*/
function add_edit_article(id) {
    if (id>0) {
        // 修改
    } else {
        var url = "{:U('Ucenter/Seo/add_article', array('call_back'=>'call_back_fun'))}";
        layer.open({
            type: 2,
            title: '发布文章',
            shadeClose: true,
            shade: 0.8,
            area: ['80%', '80%'],
            content: url,
        });
    }
}

/*回调函数,关闭窗口*/
function call_back_fun(v) {
    layer.closeAll();
    location.href = "弹出页面的URL";
}

第3步:弹出的页面

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public function add_article()
{
    header("Content-Type:text/html; charset=utf-8");
    if ($this->isPost()) {
        $postData = $this->_post();

        // TODO:数据校验

        // 写入数据库操作

        $call_back = $this->_get("call_back","","call_back_fun");
        echo "<script>parent.{$call_back}('success');</script>";
        exit();
    }

    $this->display();
}

3. 图片插件的使用

演示效果:

插件官网:http://www.uploadify.com/

第1步:HTML表单制作

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<form action="{:U('Ucenter/Seo/add_video')}" method="post" id="videoForm">
<div class="form-group">
    <label for="v_name">视频名称:</label>
    <input type="text" class="form-control" id="v_name" placeholder="视频名称" name="v_name"/>
</div>
<div class="form-group">
    <label for="cate_id">选择视频分类:</label>
    <select name="cat_id" id="cate_id" class="form-control" style="width: 300px;">
        <option value="0">请选择视频分类</option>
        <volist name="videos_category" id="vo">
            <option value="{$vo.vc_id}">{$vo.vc_name}</option>
        </volist>
    </select>
</div>
<div class="form-group">
    <label for="type">选择课程类型:</label>
    <select name="v_lesson_id" id="type" class="form-control" style="width: 300px;">
        <option value="0">请选择课程类型</option>
        <volist name="videos_lesson" id="vo" key="k">
            <option value="{$vo.l_id}">{$vo.l_name}</option>
        </volist>
    </select>
</div>
<div class="form-group">
    <label for="v_teacher">选择博主:</label>
    <select name="v_teacher_id" id="v_teacher" class="form-control" style="width: 300px;">
        <option value="0">请选择博主</option>
        <volist name="videos_teacher" id="vo" key="k">
            <option value="{$vo.t_id}">{$vo.t_name}</option>
        </volist>
    </select>
</div>
<div class="form-group">
    <label for="v_code">播放码:</label>
    <input type="text" class="form-control" id="v_code" placeholder="填写视频播放码" name="v_code"/>
</div>
<div class="form-group">
    <label for="keywords">关键字:</label>
    <input type="text" class="form-control" id="keywords" placeholder="关键字" name="keywords"/>
</div>
<div class="form-group">
    <label for="file_upload">封面图片:</label>
    <input type="file" id="file_upload" multiple="true"/>
    <img src="" style="display: none" id="upload_image" width="200"/>
    <input type="hidden" name="image" id="upload_image_input" multiple="true" value=""/>
</div>
<div class="form-group">
    <label for="description">短描述:</label>
    <textarea name="description" id="description" class="form-control" name="keywords" cols="30"
              rows="3"></textarea>
</div>
<button type="button" class="btn btn-default" onclick="checkForm()">提交</button>
<input type="reset" class="btn btn-default" value="重置">
<div></div>
</form>

第2步:引入JS,CSS文件

Select Code
1
2
3
<script src="__PUBLIC__/uploadify/jquery.min.js" type="text/javascript"></script>
<link href="__PUBLIC__/uploadify/uploadify.css" rel="stylesheet">
<script src="__PUBLIC__/uploadify/jquery.uploadify.js" type="text/javascript"></script>

第3步:编写JS

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<script type="text/javascript">
    // 检查表单内容
    function checkForm() {
        var v_name = $("input[name='v_name']").val();
        var v_code = $.trim($("input[name='v_code']").val());
        var keywords = $("input[name='keywords']").val();
        var image = $("input[name='image']").val();
        var cat_id = $("select[name='cat_id']").val();
        var v_lesson_id = $("select[name='v_lesson_id']").val();
        var v_teacher_id = $("select[name='v_teacher_id']").val();
        var description = $.trim($("textarea[name='description']").val());
        var error = "";

        if (v_name == "") {
            error += "视频名称不能为空<br />";
        }
        if (v_code == "") {
            error += "播放码不能为空<br />";
        }
        if (v_code.length != 32) {
            error += "播放码长度必须为32<br />";
        }
        if (keywords == "") {
            error += "关键字不能为空<br />";
        }
        if (image == "") {
            error += "必须上传封面图片<br />";
        }
        if (cat_id == "" || cat_id == "0") {
            error += "请选择视频类别<br />";
        }
        if (v_lesson_id == "" || v_lesson_id == "0") {
            error += "请选择课程类别<br />";
        }
        if (v_teacher_id == "" || v_teacher_id == "0") {
            error += "请选择博主<br />";
        }
        if (description == "") {
            error += "描述内容不能为空<br />";
        }
        if (description.length > 250) {
            error += "描述内容最多250字<br />";
        }

        if (error) {
            layer.alert(error);
            return false;
        }
        return $("#videoForm").submit();
    }

    var SWF = '__PUBLIC__/uploadify/uploadify.swf';
    var UPLOAD_IMG = '{:U("Home/Image/upload")}';

    $(function () {
        $("#file_upload").uploadify({
            height: 40,
            swf: SWF,
            uploader: UPLOAD_IMG,
            width: 120,
            buttonText: '图片上传',
            fileObjName: 'file',
            fileTypeExts: '*.gif;*.jpg;*.png',
            onUploadSuccess: function (file, data, response) {
                if (response) {
                    var obj = JSON.parse(data);
                    if (obj.status == 0) {
                        alert(obj.info);
                        return false;
                    }
                    $("#upload_image").attr("src", obj.img_url);
                    $("#upload_image").show();
                    $("#upload_image_input").attr("value", obj.img_url);

                }
            }
        });
    });

</script>

第4步:表单提交

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public function add_video()
{
    header("Content-Type:text/html; charset=utf-8");

    $videos_category = M("VideosCategory")->field('vc_id,vc_name')->select();
    $videos_teacher = M("VideosTeacher")->field('t_id,t_name')->select();
    $videos_lesson = M("VideosLesson")->field('l_id,l_name')->select();
    $this->assign('videos_category', $videos_category);
    $this->assign('videos_teacher', $videos_teacher);
    $this->assign('videos_lesson', $videos_lesson);

    if ($this->isPost()) {
        $postData = $this->_post();
        // TODO:数据校验

    $data = array(
            'v_name' => $postData['v_name'],
            'v_lesson_id' => $postData['v_lesson_id'],
            'v_teacher_id' => $postData['v_teacher_id'],
            'v_code' => $postData['v_code'],
            'v_picture' => $postData['image'],
            'v_keywords' => $postData['keywords'],
            'v_description' => $postData['description'],
            'zan_num' => 0,
            'create_time' => date('Y-m-d H:i:s')
        );

    $model = M('');
        $model->startTrans();
        $video_id = D("VideosInfo")->add($data);
        if (!$video_id) {
            $model->rollback();
        }

        $data_body = array(
            'video_id' => $video_id,
            'cat_id' => $postData['cat_id'],
        );

        $result = D("VideosCategoryInfo")->add($data_body);
        if ($result) {
            $model->commit();
        } else {
            $model->rollback();
        }

        $call_back = $this->_get("call_back","","call_back_fun");
        echo "<script>parent.{$call_back}('success');</script>";
        exit();
    }

    $this->display();
}

第5步:图片上传图片方法

Select Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function upload()
{
    import('ORG.Net.UploadFile');
    $upload = new UploadFile();
    $upload->maxSize = 3145728;
    $upload->allowExts = array('jpg','png','gif', 'jpeg');
    $upload->savePath = './Public/Uploads/video/';
    if (!$upload->upload()) {
        $data = array(
            'status' => 0,
            'info' => $upload->getErrorMsg(),
        );
    } else {
        $info = $upload->getUploadFileInfo();
        $data = array(
            'status' => 1,
            'info' => 'ok',
            'img_url' => ltrim($info[0]['savepath'] . $info[0]['savename'], '.'),
        );
    }
    $this->ajaxReturn($data, 'JSON');
}