appinfo = [ 'url' => '', 'c' => 'dzadsod', 'a' => 'dodzadsod', 'lang' => $_M['lang'], 'time' => date('Y-m-d H:i:s',time()) ]; $this->sqlk = $_M['table']['cloud_config']; } //需要传递值 public function set($app) { global $_M; $this->app = $app; $this->appno = $app['no']; $this->m_name = $app['m_name']; $this->newver = $app['ver']; $this->oldver = $app['oldver']; return $this; } //修改数据库版本 public function start() { global $_M; if(file_exists(INS_LOCK_FILE)){ switch ($this->newver) { case 1.1: //更新数据库 self::inssql(); //更新版本内容 self::update_1_1(); break; case 1.2: //更新版本内容 self::update_1_2(); break; case 1.3: //更新版本内容 self::update_1_3(); break; default: break; } //更新版本号 self::upver(); }else{ //创建数据表 self::inssql(); //默认系统表处理 self::systable(); //默认数据 self::default_config(); //创建栏目 [前端页面时才需要,API也不需要] // self::column(); //安装锁 self::install_lock(); } } /* + 应用新安装操作 +------------------------------------------------------------------------------------------- + up1.1 : 更新版本 +------------------------------------------------------------------------------------------- + default_config : 默认的应用配置信息方法 +------------------------------------------------------------------------------------------- + systable : 当前应用版本针对数据库表的信息 +------------------------------------------------------------------------------------------- */ // 1.1 版本 public function update_1_1() { global $_M; //执行SQL其他操作 $tview = self::tview(); foreach ($tview as $key => $val){ $tname[] = $key; $table_name = self::split_table_name($key); $table[] = $table_name; DB::query($val); } //记录表名 add_table(arrayto_string($table,'|')); $filetable = PATH_ALL_APP.$this->m_name.'/config/table'; //先获取之前已经存在的简短表名 if(file_exists($filetable)) { $tnamestr = file_get_contents($filetable); $tname = array_merge($tname,stringto_array($tnamestr,',')); }else{ //创建 makefile($filetable); } //写入 file_put_contents($filetable,arrayto_string($tname,',')); } // 1.2 版本 public function update_1_2() { global $_M; //执行SQL其他操作 $tables = self::table_field(); $table = $tname = []; foreach ($tables as $key => $val) { $tname[] = $key; $table_name = self::split_table_name($key); $table[] = $table_name; if($val) DB::query("CREATE TABLE `{$_M['config']['tablepre']}{$table_name}` ( {$val} ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8"); } //记录表名 add_table(arrayto_string($table,'|')); $filetable = PATH_ALL_APP.$this->m_name.'/config/table'; //先获取之前已经存在的简短表名 if(file_exists($filetable)) { $tnamestr = file_get_contents($filetable); $tname = array_merge($tname,stringto_array($tnamestr,',')); }else{ //创建 makefile($filetable); } //写入 file_put_contents($filetable,arrayto_string($tname,',')); } // 1.3 版本 public function update_1_3() { global $_M; //执行SQL其他操作 $tview = self::tview(); foreach ($tview as $key => $val){ $tname[] = $key; $table_name = self::split_table_name($key); $table[] = $table_name; DB::query($val); } //记录表名 add_table(arrayto_string($table,'|')); $filetable = PATH_ALL_APP.$this->m_name.'/config/table'; //先获取之前已经存在的简短表名 if(file_exists($filetable)) { $tnamestr = file_get_contents($filetable); $tname = array_merge($tname,stringto_array($tnamestr,',')); }else{ //创建 makefile($filetable); } //写入 file_put_contents($filetable,arrayto_string($tname,',')); } /* + 应用新安装操作 +------------------------------------------------------------------------------------------- + table_field : 当前应用数据创建依据 +------------------------------------------------------------------------------------------- + default_config : 默认的应用配置信息方法 +------------------------------------------------------------------------------------------- + systable : 当前应用版本针对数据库表的信息 +------------------------------------------------------------------------------------------- */ //数据库创建 protected function table_field() { global $_M; // 场所资料库 $zdytable['village'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `v_name` varchar(255) NOT NULL COMMENT '场所名称', `v_type` varchar(255) NOT NULL COMMENT '分类', `v_province` varchar(255) NOT NULL COMMENT '省', `v_city` varchar(255) NOT NULL COMMENT '市', `v_district` varchar(255) NOT NULL COMMENT '区', `v_address` varchar(255) NOT NULL COMMENT '详细地址', `v_lxname` varchar(150) NOT NULL COMMENT '相关联系人', `v_tel` text COMMENT '联系电话', `v_price` decimal(10,2) DEFAULT NULL COMMENT '场所均价', `v_psize` int(11) COMMENT '居住人口规模', `v_text` text COMMENT '备注', `v_updatetime` datetime DEFAULT NULL, `v_addtime` datetime DEFAULT NULL, UNIQUE KEY `vname` (`v_name`), PRIMARY KEY (`id`)"; // 公司资料库 // 公司地址填写采用选择城市联动的方式填写,方便后期数据查询处理筛选 $zdytable['customer'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `c_allname` varchar(255) NOT NULL COMMENT '公司全称名称', `c_name` varchar(255) NOT NULL COMMENT '公司简称名称', `c_province` varchar(255) NOT NULL COMMENT '省', `c_city` varchar(255) NOT NULL COMMENT '市', `c_district` varchar(255) NOT NULL COMMENT '区', `c_address` varchar(255) NOT NULL COMMENT '详细地址', `c_lxname` varchar(150) NOT NULL COMMENT '相关联系人', `c_tel` text COMMENT '联系电话', `c_text` text COMMENT '备注', `c_updatetime` datetime DEFAULT NULL, `c_addtime` datetime DEFAULT NULL, UNIQUE KEY `cname` (`c_name`), PRIMARY KEY (`id`)"; //公司负责人联系方式 //负责人姓名,电话,职位分类,备注 // w_tel 可做成标签,总之要满足多个录入的要求 $zdytable['workers'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `w_jid` int(11) NOT NULL COMMENT '职务id', `w_name` varchar(150) NOT NULL COMMENT '姓名', `w_tel` text COMMENT '联系电话', `w_text` text COMMENT '备注', `w_updatetime` datetime DEFAULT NULL, `w_addtime` datetime DEFAULT NULL, PRIMARY KEY (`id`)"; // 同一个广告位置 不可重复 $zdytable['elevator'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `e_vid` int(11) COMMENT '场所ID', `e_number` varchar(100) NOT NULL COMMENT '广告位编号,用于后期各表操作', `e_bno` int(11) NOT NULL COMMENT '道闸方位', `e_aps` int(11) NOT NULL COMMENT '广告位置', `e_size` varchar(255) NOT NULL COMMENT '广告位尺寸大小', `e_enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用 0 不启用,1 为启用', `e_label` text COMMENT '自主标签', `e_text` text COMMENT '备注', UNIQUE KEY `elidno` (`e_vid`,`e_bno`,`e_aps`), UNIQUE KEY `enumber` (`e_number`), PRIMARY KEY (`id`)"; // 合同资料库 // h_cid h_wid 采用联动菜单方式 // h_noticeday 可做成tab 标签形式满足多个通知天数 $zdytable['contract'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `h_number` varchar(100) NOT NULL COMMENT '合同编号,用于后期各表操作', `h_signtime` varchar(255) COMMENT '签订日期', `h_cid` int(11) COMMENT '签定公司', `h_wid` varchar(255) COMMENT '签定相关公司人员', `h_tprice` decimal(10,2) DEFAULT NULL COMMENT '总价格', `h_starttime` varchar(255) COMMENT '广告开始时间', `h_endtime` varchar(255) COMMENT '广告结束时间', `h_noticeday` varchar(255) COMMENT '提前通知天数', `h_text` text COMMENT '备注', `h_updatetime` datetime DEFAULT NULL COMMENT '修改时间', `h_addtime` datetime DEFAULT NULL COMMENT '录入时间', UNIQUE KEY `elidno` (`h_number`), PRIMARY KEY (`id`)"; // 广告投放计划单 //将合同的进度状态调整到投放计划内 $zdytable['launch'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `l_title` varchar(255) COMMENT '投放计划标题', `l_hnumber` varchar(100) NOT NULL COMMENT '合同编号', `l_enumber` text COMMENT '排期成功的广告位编号', `l_selectenum` text COMMENT '选择的广告位编号', `l_schedule` int(11) COMMENT '投放进度', `l_starttime` varchar(255) COMMENT '广告开始时间', `l_endtime` varchar(255) COMMENT '广告结束时间', `l_enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '广告排期状态 0预选,1正常 2预排', `l_type` varchar(255) NOT NULL COMMENT '分类', `l_text` text COMMENT '备注', `l_updatetime` datetime DEFAULT NULL COMMENT '修改时间', `l_addtime` datetime DEFAULT NULL COMMENT '录入时间', PRIMARY KEY (`id`)"; // 广告时间段排期表,广告位编号,合同编号,开始时间,结束时间,状态 // 排期的缓存表 $zdytable['schedule'] = " `id` char(36) NOT NULL COMMENT 'uuid', `s_lid` int(11) COMMENT '广告投放ID', `s_enumber` varchar(100) NOT NULL COMMENT '广告位编号', `s_hnumber` varchar(100) NOT NULL COMMENT '合同编号', `s_starttime` varchar(255) COMMENT '广告开始时间', `s_endtime` varchar(255) COMMENT '广告结束时间', UNIQUE KEY `slidse` (`s_lid`,`s_enumber`), PRIMARY KEY (`id`) "; // 参数配置 $zdytable['para'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `p_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '参数分类 0广告位置,1职位,2合同状态,3道闸方位', `p_order` int(11) DEFAULT '0' COMMENT '排序', `p_name` varchar(255) COMMENT '名称', `p_value` int(11) COMMENT '参数值,必须为数字', `p_text` varchar(255) COMMENT '备注', UNIQUE KEY `ptypevalue` (`p_type`,`p_value`), PRIMARY KEY (`id`)"; // 有序表,处理分割字段 $zdytable['sequence'] = " `seq` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`seq`)"; // 公司资料库 // 公司地址填写采用选择城市联动的方式填写,方便后期数据查询处理筛选 $zdytable['welog'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `openid` varchar(45) NOT NULL COMMENT '微信用户ID', `text` text COMMENT '核心内容', `content` text COMMENT '微信模板信息', `returntext` text COMMENT '返回信息', `state` tinyint(1) COMMENT '记录状态', `exetime` varchar(255) COMMENT '处理时间', `addtime` varchar(255) COMMENT '录入时间', PRIMARY KEY (`id`)"; //前台巡查人员的验证密钥密码 $zdytable['keylist'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `k_passkey` varchar(45) NOT NULL COMMENT '密钥密码', `k_basekey` text COMMENT '明密', `k_wid` varchar(255) COMMENT '相关联系人', `k_state` tinyint(1) COMMENT '密钥状态', `k_text` text COMMENT '备注', `k_addtime` varchar(255) COMMENT '新增时间', `k_updatetime` varchar(255) COMMENT '修改时间', PRIMARY KEY (`id`)"; /** * 1、增加新表 * name 配置名称 * id 添加信息自动增加, * value 配置名称值 * lang 语言[后台] **/ $zdytable['cloud_config'] = " `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `m_name` varchar(50) NOT NULL, `value` text, `lang` varchar(50) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `name_lang` (`name`,`m_name`,`lang`)"; //执行 return $zdytable; } //mysql 触发器 protected function trigger() { global $_M; //新增schedule 表的更新触发器 $table_name = self::split_table_name('schedule',true); $launch_name = self::split_table_name('launch',true); //更新触发器并没有排除两个时间字段为空的排查 $array[] = " CREATE TRIGGER `add` BEFORE INSERT ON `{$table_name}` FOR EACH ROW BEGIN IF EXISTS ( SELECT `id` FROM `{$table_name}` WHERE NOT ( s_endtime < new.s_starttime OR s_starttime > new.s_endtime ) AND s_enumber = new.s_enumber) OR EXISTS ( SELECT `id` FROM `{$launch_name}` WHERE NOT ( l_endtime < new.s_starttime OR l_starttime > new.s_endtime ) AND find_in_set( new.s_enumber, l_enumber ) AND id != new.s_lid ) THEN SIGNAL SQLSTATE 'SC001' SET MESSAGE_TEXT = '排期时间区间重复'; END IF; END; "; // 加入为空排查其他字段就无法实现更新 $array[] = " CREATE TRIGGER `up` BEFORE UPDATE ON `{$table_name}` FOR EACH ROW BEGIN IF EXISTS ( SELECT `id` FROM `{$table_name}` WHERE NOT ( s_endtime < new.s_starttime OR s_starttime > new.s_endtime ) AND s_enumber = new.s_enumber AND id != new.id ) OR EXISTS ( SELECT `id` FROM `{$launch_name}` WHERE NOT ( l_endtime < new.s_starttime OR l_starttime > new.s_endtime ) AND find_in_set( new.s_enumber, l_enumber ) AND id != new.s_lid ) THEN SIGNAL SQLSTATE 'SC002' SET MESSAGE_TEXT = '排期时间区间重复'; END IF; END; "; return $array; } //mysql 视图 protected function tview() { global $_M; //查询到期合同以及根据设置的到期天数提醒 $sequence = self::split_table_name('sequence',true); $contract = self::split_table_name('contract',true); $noticeday = self::split_table_name('noticeday',true); $array['noticeday'] = " CREATE VIEW {$noticeday} AS SELECT ct.*, substring_index( substring_index( ct.h_noticeday, ',', sq.seq ), ',',- ( 1 ) ) AS noticeday, DATE_SUB(ct.h_endtime,INTERVAL substring_index( substring_index( ct.h_noticeday, ',', sq.seq ), ',',- ( 1 ) ) DAY) AS endtime, sq.seq FROM {$sequence} AS sq INNER JOIN {$contract} AS ct ON sq.seq <= ( ( 1 + length( ct.h_noticeday ) ) - length( REPLACE ( ct.h_noticeday, ',', '' ) ) ) "; //查询微信关注用户,排除非关注的用户 $weuser = self::split_table_name('weuser',true); $nwechat_user = self::split_table_name('nwechat_user',true); $array['weuser'] = " CREATE VIEW {$weuser} AS SELECT * FROM {$nwechat_user} WHERE subscribe = 1 "; // 广告位排期统计,计算广告位的空闲,到期,投放中 $elevator = self::split_table_name('elevator',true); $launch = self::split_table_name('launch',true); $countela = self::split_table_name('countela',true); $array['countela'] = " CREATE VIEW {$countela} AS SELECT e.id, e.e_vid, e.e_number, e.e_bno, e.e_aps, e.e_enable, l.id AS l_id, l.l_title, l.l_hnumber, l.l_schedule, l.l_starttime, l.l_endtime, l.l_enable, l.l_type FROM {$elevator} AS e LEFT JOIN {$launch} AS l ON find_in_set( e.e_number, l.l_enumber ) "; return $array; } //默认配置 protected function default_config() { global $_M; //正常升级 $config = [ 'tem_ida','tem_idb','tem_idc','openid' ]; $lang = $_M['lang']; foreach ($config as $key => $val){ DB::query("INSERT INTO {$this->sqlk} (name,lang,m_name,value) VALUES ('{$key}','{$lang}','{$this->m_name}','{$val}') ON DUPLICATE KEY UPDATE value='{$val}' "); } } //系统表 protected function systable() { global $_M; //访问入口固定为app/index.php?n=XXX&c=XXX&a=XXX //定时处理入口 // $field = "no='{$this->appno}',m_name='{$this->m_name}',filename='timing.php',m_module='web',m_class='timing',m_action='@\$_GET[a]'"; // self::addsql('ifcolumn_addfile',$field); } /* + 公用安装升级方法 +------------------------------------------------------------------------------------------- + inssql : 应用数据表创建 +------------------------------------------------------------------------------------------- + upver : 修改应用版本号 +------------------------------------------------------------------------------------------- + install_lock : 创建安装锁 +------------------------------------------------------------------------------------------- */ //应用数据表创建 protected function inssql() { global $_M; $tables = self::table_field(); $table = $tname = []; foreach ($tables as $key => $val) { $tname[] = $key; $table_name = self::split_table_name($key); $table[] = $table_name; if($val) DB::query("CREATE TABLE `{$_M['config']['tablepre']}{$table_name}` ( {$val} ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8"); } //建立触发器 $trigger = self::trigger(); foreach ($trigger as $val){ DB::query($val); } //执行SQL其他操作 $tview = self::tview(); foreach ($tview as $key => $val){ $tname[] = $key; $table_name = self::split_table_name($key); $table[] = $table_name; DB::query($val); } //记录表名 add_table(arrayto_string($table,'|')); $filetable = PATH_ALL_APP.$this->m_name.'/config/table'; //先获取之前已经存在的简短表名 if(file_exists($filetable)) { $tnamestr = file_get_contents($filetable); $tname = array_merge($tname,stringto_array($tnamestr,',')); }else{ //创建 makefile($filetable); } //写入 file_put_contents($filetable,arrayto_string(array_unique($tname),',')); } //修改版本号 protected function upver() { global $_M; DB::query("UPDATE {$_M['table']['applist']} SET ver='{$this->newver}' WHERE no='{$this->appno}' AND m_name='{$this->m_name}' "); } //创建安装锁 protected function install_lock() { global $_M; if(!file_exists(INS_LOCK_FILE)) makefile(INS_LOCK_FILE); file_put_contents(INS_LOCK_FILE, json_encode($this->appinfo,JSON_UNESCAPED_UNICODE) ); } /* + 公用SQL方法 +------------------------------------------------------------------------------------------- + sqlone : 单条查询方法 +------------------------------------------------------------------------------------------- + sqlall : 批量查询方法 +------------------------------------------------------------------------------------------- + addsql : 入库方法 +------------------------------------------------------------------------------------------- + split_table_name : 拼接完整数据库名 +------------------------------------------------------------------------------------------- */ //公共查询方法 private function sqlone($tname,$where = '') { global $_M; $table = $_M['table'][$tname]; if(!$where) $where = "no='{$this->appno}'"; return DB::get_one("select * from {$table} where {$where}"); } //公共查询方法 private function sqlall($tname,$where = '') { global $_M; $table = $_M['table'][$tname]; if(!$where) $where = "no='{$this->appno}'"; return DB::get_all("select * from {$table} where {$where}"); } //公共写入方法 private function addsql($tname,$field = '') { global $_M; $table = $_M['table'][$tname]; DB::query("INSERT INTO {$table} SET {$field}"); } //拼接完整数据库名 private function split_table_name($name,$all = false) { global $_M; //公用表 $global_table = ['cloud_config','nwechat_user']; $tablename = in_array($name, $global_table)?$name:$this->m_name.'_'.$name; return $all?$_M['config']['tablepre'].$tablename:$tablename; } /* + 前端入口的创建。 +------------------------------------------------------------------------------------------- + column : 创建栏目信息 //目前的方法不适合最新版本 后期等待更正 +------------------------------------------------------------------------------------------- */ //创建前台入口API形式 protected function column_api() { global $_M; $file = self::sqlall('ifcolumn_addfile'); $dir = PATH_WEB.$this->fixed_name; if(makedir($dir)){ if(getdirpower($dir) == false) modifydirpower($dir,0777); } foreach ($file as $val) { $dirfile = $dir.'/'.$val['filename']; $action = strstr($val['m_action'],'@$_')?$val['m_action']:"'{$val['m_action']}'"; $phpstr = ""; file_put_contents($dirfile, $phpstr); } } //创建栏目信息 protected function column() { global $_M; $name = array('cn'=>'加盟店','en'=>'Join store query','tc'=>'加盟店'); foreach (array('cn','en','tc') as $k => $v) { DB::query("INSERT INTO {$_M['table']['column']} SET name='{$name[$v]}',foldername='{$this->fixed_name}',module='{$this->appno}',no_order='100',if_in='1',classtype='1',out_url='{$_M['url']['site']}{$this->fixed_name}',isshow='1',lang='{$v}',nav='1'"); } } }