在 Discuz! 论坛中,帖子的楼层号是从主题开始计的,即“楼主”是 1#,“沙发”是 2#,“板凳”是 3#,“地板”是 4#,从 5# 开始直接以数字显示,所以我们在计算中奖楼层时,应排除主题帖所在的 1#。以活动截止时的最大楼层号 1000# 为例,允许中奖的楼层数应为 999。据此设计了以下中奖算法:
1、将****年*月*日的上证指数收盘价(含两位小数)×100
2、将得到的 6 位数字按倒序排列
3、用这个新的 6 位数除以总的回复楼层数(即活动截止时的最大楼层号-1),得到余数
4、将余数+2 即为中奖楼层
以2020年9月30日上证指数收盘价为例:3218.05×100=321805,倒序后是 508123,若截止时间前的最大楼层号为 1000,那么 508123÷(1000-1)=508 余 631,则中奖楼层号为:631+2=633。
注:
股市 15:00 收盘,但更新收盘价会延迟若干秒,因此稍候查看收盘价更为准确。
论坛发帖会有延时,特别是在抢楼这种高并发的情况下,在“抢楼主题”类型中设置了结束时间后,实际结束时的最终一个回帖的时间仍然可能超过活动截止时间(比如超过 1 秒),所以应在活动说明中明确具体以哪一个楼层结束。
其它活动说明:如不按规定回复中奖无效,不重复中奖的顺延方案,中奖楼层不存在的顺延方案等。
上证指数实时获取接口:http://hq.sinajs.cn/list=sh000001
返回结果例:var hq_str_sh000001="上证指数,开盘价,昨收价,最新价,最高价,最低价,0,0,总手,金额,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,日期,时间,00,";
特别注意,传入不同股票代码返回结果数据中的保留小数位数不同,上证指数保留了四位小数,应四舍五入保留两位小数后参与计算。
删除主题时,会变更主题表 pre_forum_thread:
displayorder = -1
moderated = 1
帖子表(或分表) pre_forum_post* 该主题的所有帖子的
invisible = -1
同时 pre_forum_threadmod 会新增一条 DEL 记录,用于显示到 Discuz! 控制面板 - 内容 - 主题回收站。
删除回帖时,会变更回帖表 pre_forum_post(或分表):
invisible = -5
屏蔽回复时,会变更回复表 pre_forum_post(或分表):
status = 1
对于大型站点,庞大的主题和帖子数据,分表放到一个主题表和一个帖子表中,已经成为影响性能的一个因素。因此,急需进行分表操作来避免 MySQL 对于大数据表的频繁操作。
1、后台分表
Disucz! X2 后台重新调整了分表的机制,使得分表效率和后期站点性能得到提升。具体分表设置在 后台 -> 站长 -> 主题分表(帖子分表)。
1)主题分表
主题分表分为两种类型,一种为主表,一种为存档表。主表只有一个,存档表可以有多个。我们进行分表操作,首先进行创建存档表的操作,然后进行主题移动,将指定条件的主题移动到存档表中。
a、创建存档表
打开 source/admincp/admincp_threadsplit.php 文件,找到创建存档表的条件分支
- elseif($operation == 'addnewtable')
复制代码
首先获取当前最大的主题表 id ,然后根据 forum_thread 的建表语句,生成新的存档表(id + 1),最后更新缓存。
b、主题移动
存档表建好后,下一步就是将主题移动到这个存档表中。在选择主题的时候,可以根据提供的搜索条件,特别是“更多选项”中的搜索条件,来转移符合条件的主题。这里主要是一个搜索的过程,转移数据的过程使用 REPLACE INTO … SELECT...FROM... 语句,比较简单。
2)帖子分表
帖子分表也是要分成两步,第一步先创建帖子分表,第二步转移数据。
打开 source/admincp/admincp_postsplit.php 文件,找到帖子分表的条件分支
- elseif($operation == 'split')
复制代码
如果是对主表进行分表操作,主表必须要大于400M,见下面的条件判断
- if($status && ((!$tableid && $status['Data_length'] > 400 * 1048576) || ($tableid && $status['Data_length'])))
复制代码
在站长提交分表表单后,程序会先根据 getmaxposttableid 函数获取当前帖子表最大的 id ,然后根据已有的帖子表结构,创建新分表,并更新缓存等信息。创建成功后,开始转移数据的操作。找到条件分支
- elseif($operation == 'movepost')
复制代码
,开始转移数据的操作。当从主表中转移数据时,是根据主题表中最后回复时间正序排列的主题 tid 来获取帖子数据的。
- $query = DB::query("SELECT tid FROM ".DB::table($table)." WHERE posttableid='0' AND displayorder>='0' ORDER BY lastpost LIMIT 0, 1000");
复制代码
然后,利用 movedate 函数进行转移数据。
当从从表中转移数据时,是根据给定帖子表的 id,获取此表中first=1的帖子所属 tid,
- $query = DB::query("SELECT tid FROM ".DB::table(getposttable($fromtableid))." WHERE `first`='1' LIMIT 0, 1000")
复制代码
然后利用 movedate 函数进行转移数据。
在 movedate 函数中,根据获取到的 tid ,将属于此 tid 的帖子,利用 INSERT INTO … SELECT … FROM ...来转移数据。在此过程中,更新主题表中 posttableid 这个字段,来标识帖子的存储表。
2、主题列表页分表读取
在主题列表页,只能看到主题主表中的主题。存档表中的主题都在存档区。
在这部分的代码(source/module/forum/forum_forumdisplay.php)中,所有涉及到的主题表都以 $threadtable 这个变量代替,$threadtable 这个变量的获取,又是根据用户是否查看存档区的标识 archiveid 来判定。
- $threadtable = $_G['gp_archiveid'] && in_array($_G['gp_archiveid'], $threadtableids) ? "forum_thread_{$_G['gp_archiveid']}" : 'forum_thread';
复制代码
当用户选择非存档内容时,archiveid = 0 或者不存在,这时,直接从 forum_thread 主表来读取主题列表。当用户选择存档内容时,archiveid = 1(1 表示存档表的 id,如果查看 id 为 2 的存档表,archiveid = 2),程序会根据 archiveid 来判断从哪个存档表中去获取主题列表。
3、帖子内容页分表读取
当用户浏览帖子内容页时,程序首先利用 loadforum 函数来获取当前的主题信息。在 loadforum 函数中,
- $_G['thread'] = get_thread_by_tid($tid, '*', $addcondiction, $archiveid);
复制代码
根据提供的 tid,get_thread_by_tid 函数到主表和存档表中分表去查找,直到找到对应的主题信息。
在 source/module/forum/forum_viewthread.php 文件中,根据
- $thread = & $_G['forum_thread'];
复制代码
- $threadtable = $thread['threadtable'];
- $posttableid = $thread['posttableid'];
- $posttable = $thread['posttable'];
复制代码
这两句来判定该主题应该去哪个帖子表中去获取帖子内容列表。
4、发新主题
发表新主题时,直接往主题主表中插入数据,对应的 posttableid = 0。然后,当插入帖子数据时,通过 insertpost 函数将数据插入帖子表中。
在 insertpost 函数中,会先去判断所属主题的 posttableid 值,得到目标帖子表,然后再往该帖子表中插入帖子数据。
5、发新回复
只有在主表的主题才能回复,因此,直接根据传递的tid去获取目标帖子表,然后插入数据。这个跟发新主题时,插入帖子内容过程相同。
6、编辑帖子
同样,只有在主表中的主题的帖子才能被编辑,因此,主题都在 forum_thread 表中。需要获取的是该主题的帖子在哪个帖子表中。打开 source/include/post/post_editpost.php 文件,找到
- $posttable = getposttablebytid($_G['tid']);
复制代码
程序在开始,通过这条语句来获取目标帖子表。在 getposttablebytid 函数中,程序根据 tid ,逐个主题表进行查找,找到对应的主题信息,获取目标帖子表,然后指向后续的编辑帖子操作。
8、取消存档
存在存档区的主题,如果想取消存档,可以通过页面底部的“取消存档”来执行。
打开 source/include/topicadmin/topicadmin_restore.php 文件,可以看到取消存档,实际上仅是将放在存档表中的主题移动到了主表中。同样,存档表的获取还是通过 archiveid 这个参数来决定的。
- $threadtable = $archiveid ? "forum_thread_$archiveid" : 'forum_thread';
复制代码
从这可以看出,存档的概念仅限于主题,帖子无所谓存档的概念。