add 17
This commit is contained in:
parent
8dadd6e4c5
commit
38a0a91963
19
Dockerfile
19
Dockerfile
|
@ -110,4 +110,21 @@ RUN apk add --no-cache gettext inotify-tools
|
|||
RUN mkdir -p /data/uploads
|
||||
|
||||
# 暴露 80 端口
|
||||
EXPOSE 80
|
||||
EXPOSE 80
|
||||
|
||||
# 使用 linuxserver/firefox:latest 作为基础镜像
|
||||
FROM linuxserver/firefox:latest
|
||||
|
||||
# 安装中文字体和语言包
|
||||
RUN apt-get update && \
|
||||
apt-get install -y fonts-noto-cjk language-pack-zh-hans && \
|
||||
locale-gen zh_CN.UTF-8 && \
|
||||
update-locale LANG=zh_CN.UTF-8
|
||||
|
||||
# 设置环境变量
|
||||
ENV LANG=zh_CN.UTF-8 \
|
||||
LANGUAGE=zh_CN:zh \
|
||||
LC_ALL=zh_CN.UTF-8
|
||||
|
||||
# 继续使用基础镜像的入口点
|
||||
ENTRYPOINT ["/init"]
|
|
@ -0,0 +1,58 @@
|
|||
// browserCheck.js
|
||||
|
||||
// 检查浏览器版本的函数
|
||||
function checkBrowserVersion() {
|
||||
const userAgent = navigator.userAgent;
|
||||
const chromeMatch = userAgent.match(/Chrome\/(\d+)/);
|
||||
|
||||
if (chromeMatch) {
|
||||
const chromeVersion = parseInt(chromeMatch[1], 10);
|
||||
if (chromeVersion < 80) {
|
||||
showMustDownloadPrompt();
|
||||
} else if (chromeVersion < 100) {
|
||||
showUpdatePrompt();
|
||||
}
|
||||
} else if (userAgent.includes("MSIE") || userAgent.includes("Trident/")) {
|
||||
showUpdatePrompt();
|
||||
}
|
||||
}
|
||||
|
||||
function showUpdatePrompt() {
|
||||
const result = window.confirm(
|
||||
"检测到您的浏览器版本较低,建议更新到最新版本以获得更好的体验。是否下载新版浏览器?"
|
||||
);
|
||||
|
||||
if (result) {
|
||||
// 提供下载链接
|
||||
const link = document.createElement("a"); // 创建一个链接元素
|
||||
link.href = "/chrome.exe"; // 替换为您在 public 目录中的安装包路径
|
||||
link.download = "chrome.exe"; // 设置下载文件名
|
||||
document.body.appendChild(link); // 将链接添加到文档中
|
||||
link.click(); // 模拟点击下载
|
||||
document.body.removeChild(link); // 下载后移除链接
|
||||
|
||||
// 打开预览地址
|
||||
// window.open(previewUrl, "_blank"); // 在新标签页中打开预览地址
|
||||
}
|
||||
}
|
||||
function showMustDownloadPrompt() {
|
||||
const previewUrl = "http://192.168.139.239:8095"; // 获取预览地址
|
||||
const result = window.confirm(
|
||||
"检测到您的浏览器版本过低,可能无法正常使用网站功能。是否立即下载推荐浏览器并打开预览地址进行预览?"
|
||||
);
|
||||
|
||||
if (result) {
|
||||
// 提供下载链接
|
||||
const link = document.createElement("a"); // 创建一个链接元素
|
||||
link.href = "/chrome.exe"; // 替换为您在 public 目录中的安装包路径
|
||||
link.download = "chrome.exe"; // 设置下载文件名
|
||||
document.body.appendChild(link); // 将链接添加到文档中
|
||||
link.click(); // 模拟点击下载
|
||||
document.body.removeChild(link); // 下载后移除链接
|
||||
|
||||
// 打开预览地址
|
||||
window.open(previewUrl, "_blank"); // 在新标签页中打开预览地址
|
||||
}
|
||||
}
|
||||
// 在页面加载时检查浏览器版本
|
||||
window.onload = checkBrowserVersion;
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="browserCheck.js"></script>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Binary file not shown.
|
@ -13,7 +13,7 @@ import { Toaster } from 'react-hot-toast';
|
|||
import ThemeProvider from './providers/theme-provider';
|
||||
dayjs.locale("zh-cn");
|
||||
function App() {
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<AuthProvider>
|
||||
|
|
|
@ -65,7 +65,7 @@ export function PostDetailProvider({
|
|||
) {
|
||||
return true;
|
||||
} else if (!post?.isPublic) {
|
||||
if (keyCode === post?.id) {
|
||||
if (keyCode === post?.id || keyCode === post?.meta?.ownCode) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -7,6 +7,7 @@ import { VisitType } from "@nice/common";
|
|||
import Header from "../PostHeader/Header";
|
||||
import Content from "../PostHeader/Content";
|
||||
import { Button, Input, Skeleton } from "antd";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export default function PostDetailLayout() {
|
||||
const { post, user, canSee, setKeyCode, isLoading } =
|
||||
|
|
|
@ -10,6 +10,7 @@ import toast from "react-hot-toast";
|
|||
import { api } from "@nice/client";
|
||||
import { RoleName } from "@nice/common";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PublicOrNotSelector from "./public-or-not-selector/PublicOrNotSelector";
|
||||
|
||||
export function LetterBasicForm() {
|
||||
const { onSubmit, receiverId, termId, form } = useLetterEditor();
|
||||
|
@ -82,18 +83,23 @@ export function LetterBasicForm() {
|
|||
<TermSelect placeholder="选择信件分类" />
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
style={{ width: "100%" }}
|
||||
rules={[{ required: true, message: "请选择收件人" }]}>
|
||||
<Input
|
||||
<div className="flex gap-2">
|
||||
<Form.Item
|
||||
name="title"
|
||||
label="标题"
|
||||
style={{ width: "100%" }}
|
||||
maxLength={20}
|
||||
showCount
|
||||
placeholder="请输入信件标题"
|
||||
/>
|
||||
</Form.Item>
|
||||
rules={[{ required: true, message: "请选择收件人" }]}>
|
||||
<Input
|
||||
style={{ width: "100%" }}
|
||||
maxLength={20}
|
||||
showCount
|
||||
placeholder="请输入信件标题"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="isPublic" initialValue={true}>
|
||||
<PublicOrNotSelector />
|
||||
</Form.Item>
|
||||
</div>
|
||||
{/* Tags Input */}
|
||||
{/* <Form.Item name={["meta", "tags"]} className="mb-6">
|
||||
<Select
|
||||
|
@ -157,11 +163,7 @@ export function LetterBasicForm() {
|
|||
}}></Button> */}
|
||||
{/* Footer Actions */}
|
||||
<div className="flex flex-col-reverse sm:flex-row items-center justify-between gap-4 mt-2 ">
|
||||
<Form.Item name="isPublic" valuePropName="checked">
|
||||
<Checkbox className="text-gray-600 hover:text-gray-900 transition-colors text-sm">
|
||||
是否公开
|
||||
</Checkbox>
|
||||
</Form.Item>
|
||||
<div></div>
|
||||
<div className="flex gap-2 ">
|
||||
{
|
||||
<Form.Item name={["meta", "signature"]}>
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import React from "react";
|
||||
import { Select } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export default function PublicOrNotSelector({
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
value?: boolean;
|
||||
onChange?: (value?: boolean) => void;
|
||||
}) {
|
||||
const [isBrowserSupported, setIsBrowserSupported] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const userAgent = navigator.userAgent;
|
||||
const browserVersion = parseInt(userAgent.split("/").pop());
|
||||
setIsBrowserSupported(browserVersion >= 87);
|
||||
}, []);
|
||||
|
||||
const options = [
|
||||
{ value: true, label: "公开" },
|
||||
{ value: false, label: "私密" },
|
||||
];
|
||||
|
||||
// 处理 Antd Select 的 onChange
|
||||
const handleAntdChange = (newValue) => {
|
||||
if (onChange) {
|
||||
onChange(newValue);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理原生 select 的 onChange
|
||||
const handleNativeChange = (e) => {
|
||||
if (onChange) {
|
||||
// 将字符串 "true"/"false" 转换为布尔值
|
||||
onChange(e.target.value === "true");
|
||||
}
|
||||
};
|
||||
|
||||
if (isBrowserSupported) {
|
||||
return (
|
||||
<Select
|
||||
value={value}
|
||||
onChange={handleAntdChange}
|
||||
style={{ width: "100%" }}>
|
||||
{options.map((option) => (
|
||||
<Select.Option
|
||||
key={String(option.value)}
|
||||
value={option.value}>
|
||||
{option.label}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<select
|
||||
value={String(value)}
|
||||
onChange={handleNativeChange}
|
||||
style={{ width: "100%", height: "32px", borderRadius: "2px" }}>
|
||||
{options.map((option) => (
|
||||
<option
|
||||
key={String(option.value)}
|
||||
value={String(option.value)}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ export const env: {
|
|||
LIB_URL: string;
|
||||
HOME_URL: string;
|
||||
HOME_TEXT: string;
|
||||
PREVIEW_URL: string;
|
||||
} = {
|
||||
APP_NAME: import.meta.env.PROD
|
||||
? (window as any).env.VITE_APP_APP_NAME
|
||||
|
@ -32,6 +33,9 @@ export const env: {
|
|||
HOME_TEXT: import.meta.env.PROD
|
||||
? (window as any).env.VITE_APP_HOME_TEXT
|
||||
: import.meta.env.VITE_APP_HOME_TEXT,
|
||||
PREVIEW_URL: import.meta.env.PROD
|
||||
? (window as any).env.VITE_APP_PREVIEW_URL
|
||||
: import.meta.env.VITE_APP_PREVIEW_URL,
|
||||
};
|
||||
|
||||
console.log(env);
|
||||
|
|
|
@ -8,13 +8,16 @@ import { ModuleRegistry } from "@ag-grid-community/core";
|
|||
import { LicenseManager } from "@ag-grid-enterprise/core";
|
||||
|
||||
import { ClientSideRowModelModule } from "@ag-grid-community/client-side-row-model";
|
||||
|
||||
import { checkBrowserVersion } from "./utils/check-browser.js";
|
||||
|
||||
ModuleRegistry.registerModules([ClientSideRowModelModule]);
|
||||
|
||||
LicenseManager.setLicenseKey(
|
||||
'LICENSE_KEY_BODY[version=v3][0102]_EXPIRY_NDg4NDc0ODcwNTExMw==094bf1c7852b11df1841f4d14457ae96'
|
||||
"LICENSE_KEY_BODY[version=v3][0102]_EXPIRY_NDg4NDc0ODcwNTExMw==094bf1c7852b11df1841f4d14457ae96"
|
||||
);
|
||||
|
||||
// 在渲染之前检查浏览器版本
|
||||
checkBrowserVersion();
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
export function checkBrowserVersion() {
|
||||
const userAgent = navigator.userAgent;
|
||||
const chromeMatch = userAgent.match(/Chrome\/(\d+)/);
|
||||
|
||||
if (chromeMatch) {
|
||||
const chromeVersion = parseInt(chromeMatch[1], 10);
|
||||
if (chromeVersion < 80) {
|
||||
showUpdatePrompt();
|
||||
}
|
||||
} else if (userAgent.includes("MSIE") || userAgent.includes("Trident/")) {
|
||||
showUpdatePrompt();
|
||||
}
|
||||
}
|
||||
|
||||
export function showUpdatePrompt() {
|
||||
const result = window.confirm(
|
||||
"检测到您的浏览器版本过低,建议更新到最新版本以获得更好的体验。是否下载新版浏览器?"
|
||||
);
|
||||
|
||||
if (result) {
|
||||
// 创建下载链接
|
||||
const link = document.createElement("a");
|
||||
link.href = "/browsers/chrome_installer.exe"; // 假设安装包放在 public/browsers 目录下
|
||||
link.download = "chrome_installer.exe";
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
module.exports = async ({ page, context }) => {
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
await page.goto("http://192.168.139.239:8090", {
|
||||
waitUntil: "networkidle0",
|
||||
});
|
||||
await page.evaluate(() => {
|
||||
document.documentElement.requestFullscreen();
|
||||
});
|
||||
};
|
|
@ -231,6 +231,7 @@ export interface PostMeta {
|
|||
signature?: string;
|
||||
ip?: string;
|
||||
tags?: string[];
|
||||
ownCode?: string;
|
||||
}
|
||||
export type RowModelResult = {
|
||||
rowData: any[];
|
||||
|
|
1365
pnpm-lock.yaml
1365
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue