refactor: fix directory structure and namespaces for webman conventions

- Rename directories to lowercase: Controller→controller, Model→model, Service→service, Util→util, Bootstrap→bootstrap
- Update all namespaces from App\Xxx to app\xxx (webman convention)
- Update all import statements across the codebase
- Update route.php to use lowercase namespaces
- Remove unused CompanyFeishuApp model
- Comment out unimplemented controller routes

Following webman 2.x framework conventions:
- Models: app\model\{ClassName}
- Controllers: app\controller\{ClassName}
- Services: app\service\{ClassName}
- Utils: app\util\{ClassName}
- Middleware: app\middleware\{ClassName}

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-02-24 18:28:23 +08:00
parent 423a04a610
commit 8629f4a4ce
20 changed files with 55 additions and 341 deletions
+66
View File
@@ -0,0 +1,66 @@
<?php
namespace app\util;
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Db
{
private static ?Capsule $capsule = null;
public static function init(): void
{
if (self::$capsule !== null) {
return;
}
$config = config('database');
self::$capsule = new Capsule();
// Add connection
self::$capsule->addConnection([
'driver' => 'mysql',
'host' => getenv('DB_HOST') ?: '127.0.0.1',
'port' => getenv('DB_PORT') ?: '3306',
'database' => getenv('DB_DATABASE') ?: 'x_server_mobile',
'username' => getenv('DB_USERNAME') ?: 'root',
'password' => getenv('DB_PASSWORD') ?: '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
]);
// Set event dispatcher
self::$capsule->setEventDispatcher(new Dispatcher(new Container()));
// Make this Capsule instance available globally via static methods
self::$capsule->setAsGlobal();
// Setup the Eloquent ORM
self::$capsule->bootEloquent();
}
public static function connection(?string $name = null): \Illuminate\Database\Connection
{
if (self::$capsule === null) {
self::init();
}
return self::$capsule->connection($name);
}
public static function table(string $table): \Illuminate\Database\Query\Builder
{
return self::connection()->table($table);
}
public static function raw(string $value): \Illuminate\Database\Query\Expression
{
return self::connection()->raw($value);
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace app\util;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Exception;
class JwtUtil
{
private static string $secret = 'your-secret-key-change-in-production';
private static int $expire = 86400 * 7; // 7 days
/**
* 生成 Token
*/
public static function encode(array $data): string
{
$payload = array_merge($data, [
'iat' => time(),
'exp' => time() + self::$expire,
]);
return JWT::encode($payload, self::$secret, 'HS256');
}
/**
* 解析 Token
*/
public static function decode(string $token): ?array
{
try {
$decoded = JWT::decode($token, new Key(self::$secret, 'HS256'));
return (array) $decoded;
} catch (Exception $e) {
return null;
}
}
/**
* 验证 Token
*/
public static function verify(string $token): bool
{
return self::decode($token) !== null;
}
}
+170
View File
@@ -0,0 +1,170 @@
<?php
namespace app\util;
/**
* 多语言翻译类
* 支持:中文(zh)、英文(en)、俄语(ru)、西语(es)、法语(fr)
*/
class Lang
{
private static ?array $translations = null;
private static string $locale = 'zh';
private static string $fallbackLocale = 'zh';
/**
* 支持的语言列表
*/
public const SUPPORTED_LOCALES = ['zh', 'en', 'ru', 'es', 'fr'];
/**
* 语言名称映射
*/
public const LOCALE_NAMES = [
'zh' => '简体中文',
'en' => 'English',
'ru' => 'Русский',
'es' => 'Español',
'fr' => 'Français',
];
/**
* 初始化翻译
*/
private static function loadTranslations(): void
{
if (self::$translations !== null) {
return;
}
self::$translations = [];
foreach (self::SUPPORTED_LOCALES as $locale) {
$file = base_path() . "/lang/{$locale}.php";
if (file_exists($file)) {
self::$translations[$locale] = require $file;
}
}
}
/**
* 设置当前语言
*/
public static function setLocale(string $locale): void
{
if (in_array($locale, self::SUPPORTED_LOCALES)) {
self::$locale = $locale;
}
}
/**
* 获取当前语言
*/
public static function getLocale(): string
{
return self::$locale;
}
/**
* 从请求中获取语言
*/
public static function detectFromRequest(): string
{
// 从请求头获取语言
$request = \request();
$acceptLanguage = $request->header('Accept-Language');
if ($acceptLanguage) {
// 解析 Accept-Language 头
$locales = explode(',', $acceptLanguage);
foreach ($locales as $locale) {
$locale = trim(strstr($locale, ';', true));
$locale = substr($locale, 0, 2);
if (in_array($locale, self::SUPPORTED_LOCALES)) {
return $locale;
}
}
}
// 从查询参数获取
$lang = $request->input('lang');
if ($lang && in_array($lang, self::SUPPORTED_LOCALES)) {
return $lang;
}
return self::$fallbackLocale;
}
/**
* 翻译文本
*
* @param string $key 翻译键,使用点号分隔,如 'common.confirm'
* @param array $params 替换参数
* @param string|null $locale 指定语言,null 则使用当前语言
* @return string 翻译后的文本
*/
public static function get(string $key, array $params = [], ?string $locale = null): string
{
self::loadTranslations();
$locale = $locale ?? self::$locale;
// 获取翻译值
$value = self::getTranslationValue($key, $locale);
// 替换参数
if (!empty($params)) {
foreach ($params as $search => $replace) {
$value = str_replace(':' . $search, $replace, $value);
$value = str_replace('{' . $search . '}', $replace, $value);
}
}
return $value;
}
/**
* 获取翻译值
*/
private static function getTranslationValue(string $key, string $locale): string
{
$keys = explode('.', $key);
$value = self::$translations[$locale] ?? [];
foreach ($keys as $k) {
if (isset($value[$k])) {
$value = $value[$k];
} else {
// 尝试使用回退语言
if ($locale !== self::$fallbackLocale) {
return self::getTranslationValue($key, self::$fallbackLocale);
}
return $key;
}
}
return is_string($value) ? $value : $key;
}
/**
* 判断翻译是否存在
*/
public static function has(string $key, ?string $locale = null): bool
{
self::loadTranslations();
$locale = $locale ?? self::$locale;
$keys = explode('.', $key);
$value = self::$translations[$locale] ?? [];
foreach ($keys as $k) {
if (isset($value[$k])) {
$value = $value[$k];
} else {
return false;
}
}
return true;
}
}