Files
dafuweng/addons/webman/controller/AppVersionController.php
2026-03-02 13:44:38 +08:00

275 lines
12 KiB
PHP

<?php
namespace addons\webman\controller;
use addons\webman\Admin;
use addons\webman\form\MyEditor;
use addons\webman\model\AppVersion;
use addons\webman\model\Channel;
use ExAdmin\ui\component\form\Form;
use ExAdmin\ui\component\form\Watch;
use ExAdmin\ui\component\grid\card\Card;
use ExAdmin\ui\component\grid\grid\Filter;
use ExAdmin\ui\component\grid\grid\Grid;
use ExAdmin\ui\component\grid\tabs\Tabs;
use ExAdmin\ui\support\Request;
use RarArchive;
use Respect\Validation\Exceptions\Exception;
use ZipArchive;
/**
* 版本管理
*/
class AppVersionController
{
protected $model;
public function __construct()
{
$this->model = plugin()->webman->config('database.app_version_model');
}
/**
* 版本
* @auth true
* @return Card
*/
public function index(): Card
{
return Card::create(Tabs::create()
->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID), $this->androidList())
->pane(admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS), $this->iosList())
->type('card')
->destroyInactiveTabPane()
);
}
/**
* 安装版本
* @return Grid
*/
public function androidList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->model()->where('system_key', AppVersion::SYSTEM_KEY_ANDROID)->orderBy('id', 'desc');
$this->getList($grid, AppVersion::SYSTEM_KEY_ANDROID);
});
}
/**
* 苹果版本
* @return Grid
*/
public function iosList(): Grid
{
return Grid::create(new $this->model(), function (Grid $grid) {
$grid->model()->where('system_key', AppVersion::SYSTEM_KEY_IOS)->orderBy('id', 'desc');
$this->getList($grid, AppVersion::SYSTEM_KEY_IOS);
});
}
/**
* 版本列表
* @param $grid
* @param $systemKey
*/
public function getList($grid, $systemKey)
{
$grid->title(admin_trans('app_version.title'));
$exAdminFilter = Request::input('ex_admin_filter', []);
if (isset($exAdminFilter['created_at_start']) && !empty($exAdminFilter['created_at_start'])) {
$grid->model()->whereDate('created_at', '>=', $exAdminFilter['created_at_start']);
}
if (isset($exAdminFilter['created_at_end']) && !empty($exAdminFilter['created_at_end'])) {
$grid->model()->whereDate('created_at', '<=', $exAdminFilter['created_at_end']);
}
$grid->autoHeight();
$grid->bordered(true);
$grid->column('channel.name', admin_trans('channel.fields.name'))->align('center');
$grid->column('system_key', admin_trans('app_version.fields.system_key'))->align('center');
$grid->column('app_version', admin_trans('app_version.fields.app_version'));
$grid->column('app_version_key', admin_trans('app_version.fields.app_version_key'))->align('center');
$grid->column('apk_url', admin_trans('app_version.fields.apk_url'))->align('center');
$grid->column('force_update', admin_trans('app_version.fields.force_update'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('hot_update', admin_trans('app_version.fields.hot_update'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('regular_update', admin_trans('app_version.fields.regular_update'))->align('center');
$grid->column('notes', admin_trans('app_version.fields.notes'))->align('center');
$grid->column('status', admin_trans('app_version.fields.status'))->switch([[1 => ''], [0 => '']])->align('center');
$grid->column('created_at', admin_trans('app_version.fields.created_at'))->align('center');
$grid->hideDelete();
$grid->hideSelection();
$grid->filter(function (Filter $filter) {
$filter->eq()->select('department_id')
->showSearch()
->style(['width' => '200px'])
->dropdownMatchSelectWidth()
->placeholder(admin_trans('channel.fields.name'))
->remoteOptions(admin_url(['addons-webman-controller-ChannelController', 'getDepartmentOptions']));
$filter->eq()->select('status')
->placeholder(admin_trans('app_version.fields.status'))
->options([
1 => admin_trans('post.normal'),
0 => admin_trans('post.disable')
]);
$filter->form()->hidden('created_at_start');
$filter->form()->hidden('created_at_end');
$filter->form()->dateRange('created_at_start', 'created_at_end', '')->placeholder([admin_trans('public_msg.created_at_start'), admin_trans('public_msg.created_at_end')]);
});
$grid->setForm()->drawer($this->form($systemKey));
$grid->quickSearch();
}
/**
* 添加修改版本
* @auth true
*/
public function form($systemKey): Form
{
ini_set('memory_limit', '512M');
Form::extend('myEditor', MyEditor::class);
return Form::create(new $this->model, function (Form $form) use ($systemKey) {
$form->title(admin_trans('app_version.title'));
$form->radio('system_key', admin_trans('app_version.fields.system_key'))
->button()
->default($systemKey)
->options([
AppVersion::SYSTEM_KEY_ANDROID => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_ANDROID),
AppVersion::SYSTEM_KEY_IOS => admin_trans('app_version.system_key.' . AppVersion::SYSTEM_KEY_IOS),
])->required();
$form->dateTime('regular_update', admin_trans('app_version.fields.regular_update'))->required();
$form->select('department_id', admin_trans('slider.fields.department_id'))
->options($this->getChannelOptions())->required();
$form->text('app_version', admin_trans('app_version.fields.app_version'))->rule([
'regex:/^\d+\.\d+\.\d+$/' => admin_trans('app_version.app_version_regex')
])->maxlength(50)->required();
$form->text('app_version_key', admin_trans('app_version.fields.app_version_key'))->disabled(true)->maxlength(50)->required();
$form->watch([
'app_version' => function ($value, Watch $watch) {
$versionNumbers = explode('.', $value);
$newVersion = implode('', $versionNumbers);
$watch['app_version_key'] = $newVersion;
},
]);
$form->row(function (Form $form) {
$form->switch('status', admin_trans('app_version.fields.status'))->span(8)->required();
$form->switch('force_update', admin_trans('app_version.fields.force_update'))->span(8)->required();
$form->switch('hot_update', admin_trans('app_version.fields.hot_update'))
->default(0)
->when('==', 1, function (Form $form) {
$form->file('apk_url', admin_trans('app_version.hot_apk_url'))
->directory('app_version')
->type('file')
->ext(['zip'])
->chunkSize(1)
->chunk()
->limit(1)
->fileSize('200MB')->hideFinder()->required();
})->when('==', 0, function (Form $form) {
$form->text('apk_url', admin_trans('app_version.fields.apk_url'))->ruleUrl()->maxlength(200)->required();
})
->span(8)
->required();
}, null);
$form->textarea('notes', admin_trans('app_version.fields.notes'))->maxlength(125)->bindAttr('rows', 3);
$form->myEditor('update_content', admin_trans('app_version.fields.update_content'));
$form->hidden('user_id')->value(!empty(Admin::user()) ? Admin::user()->id : 0);
$form->hidden('user_name')->value(!empty(Admin::user()) ? Admin::user()->username : '');
$form->hidden('hot_update_url');
$form->layout('vertical');
$form->saving(function (Form $form) {
$apkUrl = $form->input('apk_url');
$hotUpdate = $form->input('hot_update');
$hotUpdateUrl = $form->input('hot_update_url');
$appVersionKey = $form->input('app_version_key');
if (!$apkUrl) {
return message_error(admin_trans('app_version.missing_package_address'));
}
if (!$appVersionKey) {
return message_error(admin_trans('app_version.app_version_key_not_found'));
}
if (AppVersion::query()->where('department_id', $form->input('department_id'))->where('app_version_key', $appVersionKey)->exists()) {
return message_error(admin_trans('app_version.app_version_key_exists'));
}
if ($hotUpdate == 1) {
$apkUrl = str_replace(env('APP_DOMAIN'), '', $apkUrl);
if (!file_exists(public_path() . $apkUrl)) {
return message_error(admin_trans('app_version.upload_update_package'));
}
if (empty($hotUpdateUrl)) {
$extension = pathinfo($apkUrl, PATHINFO_EXTENSION);
$fileName = pathinfo($apkUrl, PATHINFO_FILENAME);
if (!$extension || !$fileName) {
return message_error(admin_trans('app_version.hot_apk_url_error'));
}
// 解压压缩包
$hotUrl = $this->decompression($appVersionKey, $extension, $apkUrl);
$form->input('hot_update_url', $hotUrl);
}
}
});
});
}
/**
* 筛选部门/渠道
* @return array
*/
public function getChannelOptions(): array
{
$channelList = Channel::query()->orderBy('created_at', 'desc')->get();
$data = [];
/** @var Channel $channel */
foreach ($channelList as $channel) {
$data[$channel->department_id] = $channel->name;
}
return $data;
}
/**
* @param $appVersionKey
* @param string $type
* @param string $file
* @return string|void
* @throws \Exception
*/
public function decompression($appVersionKey, string $type = '', string $file = '')
{
try {
$file = public_path() . $file;
$savePath = '/storage/app_version/' . $appVersionKey;
$newPath = public_path() . $savePath;
if (!file_exists($newPath)) {
//检查是否有该文件夹,如果没有就创建,并给予最高权限
mkdir($newPath, 0755, true);
}
switch ($type) {
case 'zip':
$zip = new ZipArchive;
if ($zip->open($file) === TRUE) {
$zip->extractTo($newPath);
$zip->close();
return env('APP_DOMAIN') . $savePath;
} else {
throw new \Exception(admin_trans('app_version.decompression_failed'));
}
case 'rar':
$file = RarArchive::open($file);
if ($file !== FALSE) {
$entries = $file->getEntries();
foreach ($entries as $entry) {
$entry->extract($newPath);
}
$file->close();
return env('APP_DOMAIN') . $savePath;
} else {
throw new \Exception(admin_trans('app_version.decompression_failed'));
}
}
} catch (Exception $e) {
throw new \Exception($e->getMessage());
}
}
}