来zm好长时间了 对yii有了一定的了解,最近做了一个需求觉得有必要进行总结:
任务需求:
1.上传:从一张数据表a中按照已经拟定的条件筛选出数据然后写入另外一张表b中,a中大概有33万条数据 77个字段,筛选的数据有接近10万条数据。
2.分发:然后再从这10万条数据中进行随机分配给N个人N条,然后生成excel文档。
3:下载 对文档进行打包下载;
4:上传结果文档跟新数据库。
做这个需求用了两个星期的时间 是遇到无数个坎。显示遇到条件写不对。数据筛选不正确,
而后是数据分发 生成文档 最后是下载 打包压缩
在生成文档那刚开始用的是上传csv文件 后来突然csv文件读取乱码,无法处理。我的csv和客服的csv文件上传一个能读 一个不能读,然后就改成xls就能都读取了。
然后生成dir目录的时候是生成xls文档,然后还上传这个文档。
用csv文件下载能下载 上传读取时乱码,所以干脆统一格式 生成xls文件还上传xls文件。
writeXlsx和readXlsx 这一对方法。
writeCsv=>readCsv 这以是一对方法 只能用于csv的文件读取。
最后下载:下载之前对文件进行打包,一开始打的报都带有服务器的跟路径
下载代码如下:
private function create_zip($path,$filename){
$zip = new \ZipArchive();
if($zip->open($filename.'.zip', \ZipArchive::CREATE | \ZipArchive::OVERWRITE)) {
$this->addFileToZip($path, $zip);//调用方法,对要打包的根目录进行操作,并将ZipArchive的对象传递给方法
$zip->close(); //关闭处理的zip文件
}
}
private function addFileToZip($path,$zip){
$handler=opendir($path); //打开当前文件夹由$path指定。
while(($filename=readdir($handler))!==false){
if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’,不要对他们进行操作
if(is_dir($path."/".$filename)){
$this->addFileToZip($path."/".$filename, $zip);// 如果只写第一个的话 文件会带类路径(从服务器的根目录开始)
}else{
$zip->addFile($path."/".$filename,$filename);
}
}
}
closedir($handler);
}
private function deleteDirFile($dirpath){
$handler=opendir($dirpath); //打开当前文件夹由$path指定。
while(($filename=readdir($handler))!==false){
if($filename != "." && $filename != ".."){//文件夹文件名字为'.'和‘..’,不要对他们进行操作
if(is_dir($dirpath."/".$filename)){
$this->deleteDie($dirpath."/".$filename);
}else{
unlink($dirpath."/".$filename);
}
}
}
closedir($handler);
}
// 是否展示下载按钮
public function actionIsDownload(){
// 判断是否已经生成lawcase2021-11-11的目录 判断其中的文件个数
$date = date('Y-m-d',time());
$path = Yii::getAlias('@runtime/lawcase/'.$date);
if(!is_dir($path)){
return false;
}
$filename = Yii::getAlias('@runtime/lawcase/lawcase'.$date.'.csv');
// 读取上传的分配任务文档
$staffarr = $this->GetStaffInfo($filename);
$peoplelen = count($staffarr);
$dir = opendir($path);
$filen = 0;
while($filename = readdir($dir)) {
if($filename!="." && $filename !="..") {
$filename = $path."/".$filename;
if(is_dir($filename)) {
// $dirn++;
// getdirnum($filename); //递归,就可以查看所有子目录
} else {
$filen++;
}
}
}
closedir($dir);
if($peoplelen == $filen){
return true;
}
}
// 案源C
if($value['case_c'] > 0){
$start = 1;
$sql = "SELECT * FROM public_sea WHERE registrant_name<>'".$value['name'] ."' AND case_dict = 'C' order by rand() limit 1";
// 循环插入历史表
while(true){
$case_rand = $query->createCommand($sql)->queryOne(); // 随机分配一条案源给客服和谈案
if(empty($case_rand)){
break;
}
if(!in_array($case_rand['case_id'],$his_ids)){
// 插入历史表中
$hres = $this->actionInsertHistory($case_rand,$value['name']);
if($hres === "ok"){
$case_rand['name'] = $value['name'];
$case_rand['case_id'] = $case_rand['case_id']."\t";
$staff_case_arr[] = $case_rand; // 加入用户数组 导出使用
$start++; // 计算没个人导出的案源总数
array_push($his_ids,$case_rand['case_id']);
}elseif($hres === "exists"){
continue;
}else{
$transaction->rollBack();
return ['status'=>false,'toast'=>"分配结果插入历史表失败".$hres];
}
}else{
continue;
}
if($start > $value['case_c']){
break;
}
}
}
上面是根据条件从表b中随机筛入一条数据给一个人,如果历史表c有则在循环随机抽一条数据,历史表没有就插入历史表。
这个一开始做的事 循环完一个人的任务就找到分发的数据,就导出这个人的表,但是导出的表出现了名称和文件重复。找不到原因就换个思路写。将所有人的数据全部获取到存在缓存中
然后统一一次性生成10个人的文档文档。这次就可以了。(有问题并且找不到原因就换个思路做)
其实一开始的时候生成公海的内容页出现了一次问题 ,因为a表数据过大找到10万条数据,然后循环插入b表 就导致内存溢出,后来就分页写的(后来想到有yield和ob函数,不知道对打数据循环有没有好处)
就先记到这吧 有想起来的 以后再加