Merge branch 'ai-hub' into ai-hub-dark

This commit is contained in:
ccnetcore
2026-01-21 21:49:00 +08:00
14 changed files with 380 additions and 30 deletions

View File

@@ -0,0 +1,60 @@
import type { Plugin } from 'vite';
import { execSync } from 'node:child_process';
import path from 'node:path';
/**
* 获取 Git 提交哈希值插件
* Git 仓库在上一级目录
*/
export default function gitHashPlugin(): Plugin {
let gitHash = 'unknown';
let gitBranch = 'unknown';
let gitDate = 'unknown';
try {
// Git 仓库在上一级目录
const execOptions = { cwd: path.resolve(__dirname, '../../..'), encoding: 'utf-8' as BufferEncoding };
// 获取完整的 commit hash
gitHash = execSync('git rev-parse HEAD', execOptions)
.toString()
.trim();
// 获取短 hash (前7位)
const shortHash = gitHash.substring(0, 7);
// 获取分支名
gitBranch = execSync('git rev-parse --abbrev-ref HEAD', execOptions)
.toString()
.trim();
// 获取提交时间
gitDate = execSync('git log -1 --format=%cd --date=iso', execOptions)
.toString()
.trim();
console.log(`\n📦 Git Info:`);
console.log(` Branch: ${gitBranch}`);
console.log(` Commit: ${shortHash}`);
console.log(` Date: ${gitDate}\n`);
gitHash = shortHash; // 使用短 hash
} catch (error: any) {
console.warn('⚠️ 无法获取 Git 信息:', error?.message || error);
}
return {
name: 'vite-plugin-git-hash',
config() {
// 在 config 钩子中返回配置
return {
define: {
__GIT_HASH__: JSON.stringify(gitHash),
__GIT_BRANCH__: JSON.stringify(gitBranch),
__GIT_DATE__: JSON.stringify(gitDate),
__BUILD_TIME__: JSON.stringify(new Date().toISOString()),
},
};
},
};
}

View File

@@ -10,12 +10,14 @@ import Components from 'unplugin-vue-components/vite';
import viteCompression from 'vite-plugin-compression';
import envTyped from 'vite-plugin-env-typed';
import gitHashPlugin from './git-hash';
import createSvgIcon from './svg-icon';
const root = path.resolve(__dirname, '../../');
function plugins({ mode, command }: ConfigEnv): PluginOption[] {
return [
gitHashPlugin(),
UnoCSS(),
envTyped({
mode,

View File

@@ -112,7 +112,7 @@
<body>
<!-- 加载动画容器 -->
<div id="yixinai-loader" class="loader-container">
<div class="loader-title">意心Ai 3.2</div>
<div class="loader-title">意心Ai 3.3</div>
<div class="loader-subtitle">海外地址仅首次访问预计加载约10秒无需梯子</div>
<div class="loader-logo">
<div class="pulse-box"></div>

View File

@@ -26,6 +26,17 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.use(store);
// 输出构建信息
console.log(
`%c 意心AI 3.3 %c Build Info `,
'background:#35495e; padding: 4px; border-radius: 3px 0 0 3px; color: #fff',
'background:#41b883; padding: 4px; border-radius: 0 3px 3px 0; color: #fff',
);
// console.log(`🔹 Git Branch: ${__GIT_BRANCH__}`);
console.log(`🔹 Git Commit: ${__GIT_HASH__}`);
// console.log(`🔹 Commit Date: ${__GIT_DATE__}`);
// console.log(`🔹 Build Time: ${__BUILD_TIME__}`);
// 挂载 Vue 应用
// mount 完成说明应用初始化完毕,此时手动通知 loading 动画结束
app.mount('#app');

View File

@@ -130,6 +130,49 @@ function handleRemove(file: UploadFile) {
fileList.value.splice(index, 1);
}
// Handle paste event for reference images
function handlePaste(event: ClipboardEvent) {
const items = event.clipboardData?.items;
if (!items) return;
for (const item of items) {
if (item.type.startsWith('image/')) {
event.preventDefault();
if (fileList.value.length >= 2) {
ElMessage.warning('最多只能上传2张参考图');
return;
}
const file = item.getAsFile();
if (!file) return;
// Check file size
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
ElMessage.error('图片大小不能超过 5MB!');
return;
}
// Create object URL for preview
const url = URL.createObjectURL(file);
const filename = `pasted-image-${Date.now()}.${file.type.split('/')[1] || 'png'}`;
const uploadFile: UploadUserFile = {
name: filename,
url,
raw: file,
uid: Date.now(),
status: 'ready',
};
fileList.value.push(uploadFile);
ElMessage.success('已粘贴图片');
break; // Only handle the first image
}
}
}
function fileToBase64(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
@@ -356,10 +399,14 @@ defineExpose({
onMounted(() => {
fetchTokens();
fetchModels();
// Add paste event listener for reference images
document.addEventListener('paste', handlePaste);
});
onUnmounted(() => {
stopPolling();
// Remove paste event listener
document.removeEventListener('paste', handlePaste);
});
</script>
@@ -474,7 +521,7 @@ onUnmounted(() => {
</div>
</el-upload>
<div class="text-xs text-gray-400 mt-2 flex justify-between items-center flex-wrap gap-2">
<span>最多2张< 5MB (支持 JPG/PNG/WEBP)</span>
<span>最多2张< 5MB (支持 JPG/PNG/WEBP可粘贴)</span>
<el-checkbox v-model="compressImage" label="压缩图片" size="small" />
</div>
</div>

View File

@@ -1 +1,12 @@
declare module "virtual:svg-icons-register";
// Git 构建信息
declare const __GIT_HASH__: string;
declare const __GIT_BRANCH__: string;
declare const __GIT_DATE__: string;
declare const __BUILD_TIME__: string;
// 全局加载器方法
interface Window {
__hideAppLoader?: () => void;
}