feat: 更新 ESLint 和 Prettier 配置,增强代码质量管理
- 在 .gitignore 中添加 public/audio/* 以忽略音频文件。 - 更新 bun.lock,添加 eslint-config-prettier 和 eslint-plugin-prettier 依赖,确保 ESLint 与 Prettier 的兼容性。 - 修改 eslint.config.ts,整合 Prettier 规则,优化代码风格一致性。 - 在 package.json 中添加 lint:fix 和 format 脚本,简化代码格式化和修复流程。 - 更新 tailwind.config.ts 和其他组件文件,统一代码风格,提升可读性。
This commit is contained in:
1 parent
5d00adc1a5
commit
76c67b492e
216 files changed
+12454
-13976
No files matched your search
@@ -1,127 +0,0 @@
|
||||
$.extend({
|
||||
getUrlVars: function(){
|
||||
var vars = [], hash;
|
||||
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
|
||||
for(var i = 0; i < hashes.length; i++)
|
||||
{
|
||||
hash = hashes[i].split('=');
|
||||
vars.push(hash[0]);
|
||||
vars[hash[0]] = hash[1];
|
||||
}
|
||||
return vars;
|
||||
},
|
||||
getUrlVar: function(name){
|
||||
return $.getUrlVars()[name];
|
||||
}
|
||||
});
|
||||
|
||||
var lesson="yuxiang"
|
||||
|
||||
var videoajax = videoAjax();
|
||||
videoajax.setHost("/");
|
||||
|
||||
//设置我的自定义数据(所有的自定义数据都设置在第一个课时ID上,以key来区分不同的类型)
|
||||
function setLtDefine(key,value){
|
||||
if(iscallyb){
|
||||
setUserDefine(1,key,value);
|
||||
}else{
|
||||
sessionStorage.setItem(lesson+"_"+key,value);
|
||||
}
|
||||
}
|
||||
|
||||
var mycstr9 = "";
|
||||
//获取定义数据
|
||||
function getLtDefine(key){
|
||||
if(iscallyb){
|
||||
let cstr = "";
|
||||
if(mycstr9 == ""){
|
||||
let cstr = getUsersDefine(1, emykey);
|
||||
if(cstr == undefined || cstr == null || cstr == "null" || cstr == ""){
|
||||
mycstr9 = getFutureDa(10);
|
||||
setLtDefine(emykey, mycstr9);
|
||||
}else{
|
||||
mycstr9 = cstr;
|
||||
}
|
||||
}
|
||||
cstr = mycstr9;
|
||||
let str = (cstr == undefined || cstr==null || cstr=="null")?"":cstr;
|
||||
getCurrentDa(str);
|
||||
var objitem = getUserDefine(1,key);
|
||||
return (objitem == undefined || objitem==null || objitem=="null")?"":objitem;
|
||||
}else{
|
||||
// let cstr = sessionStorage.getItem(lesson+"_"+emykey);
|
||||
// let str = (cstr == undefined || cstr==null || cstr=="null")?"":cstr;
|
||||
// getCurrentDa(str);
|
||||
var itemvalue = sessionStorage.getItem(lesson+"_"+key);
|
||||
return (itemvalue == undefined || itemvalue==null || itemvalue=="null")?"":itemvalue;
|
||||
}
|
||||
}
|
||||
|
||||
//设置课程笔记10002
|
||||
function setCourseNotepad(collect){
|
||||
setLtDefine(10002,$.toJSON(collect));
|
||||
}
|
||||
//获取课程笔记10002
|
||||
function getCourseNotepad(){
|
||||
return (getLtDefine(10002) == undefined || getLtDefine(10002) == null || getLtDefine(10002) == "") ? ["","","","","","","","",""] : $.parseJSON(getLtDefine(10002));
|
||||
}
|
||||
|
||||
//lessonId(课时唯一ID)
|
||||
export function setUserDefine(lessonId,key,value) {
|
||||
var param = { "lessonId": lesson+"_"+lessonId, "key": key, "content": value };
|
||||
videoajax.addUserDefine(param);
|
||||
}
|
||||
//获取用户自定义数据
|
||||
export function getUserDefine(lessonId,key) {
|
||||
var param = { "lessonId": lesson+"_"+lessonId, "order": key };
|
||||
var content = "";
|
||||
videoajax.getUserDefineInfoByUser(param, function (data) {
|
||||
console.log(data)
|
||||
if (data && data.code == 200) {
|
||||
var json = data.data.value || {};
|
||||
var contents = json[0].content || "";
|
||||
content = contents;
|
||||
}else{
|
||||
content = "";
|
||||
}
|
||||
});
|
||||
return content;
|
||||
}
|
||||
|
||||
//获取【所有】用户自定义数据
|
||||
export function getUsersDefine(lessonId,key) {
|
||||
var param = { "lessonId": lesson+"_"+lessonId, "order": key };
|
||||
var content = "";
|
||||
videoajax.getUserDefineInfo(param, function (data) {
|
||||
if (data && data.code == 200) {
|
||||
//console.info(data);
|
||||
var json = data.data.value || {};
|
||||
if(json.length > 1){
|
||||
if(key == emykey){
|
||||
let mdate = new Date(Math.max.apply(null, json.map(item => new Date(item.content))));
|
||||
content = formatDateFromMilliseconds(mdate);
|
||||
}else{
|
||||
content = json;
|
||||
}
|
||||
}else{
|
||||
content = json[0].content || "";
|
||||
}
|
||||
}else{
|
||||
content = "";
|
||||
}
|
||||
});
|
||||
return content;
|
||||
}
|
||||
|
||||
//根据课时顺序号(所处课程的第几课时)更新对应易班平台上的每个环节进度
|
||||
export function setCourseTimeProgress(order){
|
||||
//var courseid = getCookie(lesson+"_course_id");//获取url链接的课程ID
|
||||
var courseid = getLtDefine("10000");
|
||||
console.info("courseid:" + courseid + " order:" + order);
|
||||
if (iscallyb && courseid != undefined && courseid != null && courseid != "") {
|
||||
if (order > 0) {
|
||||
var param2 = { "order": order, "co": courseid, "process": 100 };
|
||||
videoajax.finishCourse(param2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
// 声明外部依赖(由运行环境提供)
|
||||
declare const $: any
|
||||
declare const iscallyb: boolean
|
||||
declare const emykey: string
|
||||
declare function videoAjax(): VideoAjax
|
||||
declare function getFutureDa(days: number): string
|
||||
declare function getCurrentDa(str: string): void
|
||||
declare function formatDateFromMilliseconds(date: Date): string
|
||||
|
||||
interface UserDefineParam {
|
||||
lessonId: string
|
||||
key?: string | number
|
||||
order?: string | number
|
||||
content?: string
|
||||
}
|
||||
|
||||
interface VideoAjaxResponseItem {
|
||||
content?: string
|
||||
}
|
||||
|
||||
interface VideoAjaxResponse {
|
||||
code: number
|
||||
data: {
|
||||
value?: VideoAjaxResponseItem[] | string
|
||||
}
|
||||
}
|
||||
|
||||
interface VideoAjax {
|
||||
setHost(host: string): void
|
||||
addUserDefine(param: UserDefineParam): void
|
||||
getUserDefineInfoByUser(
|
||||
param: UserDefineParam,
|
||||
callback: (data: VideoAjaxResponse | undefined) => void
|
||||
): void
|
||||
getUserDefineInfo(
|
||||
param: UserDefineParam,
|
||||
callback: (data: VideoAjaxResponse | undefined) => void
|
||||
): void
|
||||
finishCourse(param: { order: number; co: string; process: number }): void
|
||||
}
|
||||
|
||||
// 扩展 jQuery,获取 URL 参数
|
||||
$.extend({
|
||||
getUrlVars(): string[] & Record<string, string | undefined> {
|
||||
const vars: any[] & Record<string, string | undefined> = [] as any
|
||||
let hash: string[]
|
||||
const queryIndex = window.location.href.indexOf('?')
|
||||
if (queryIndex === -1) return vars
|
||||
const hashes = window.location.href
|
||||
.slice(queryIndex + 1)
|
||||
.split('&')
|
||||
.filter(Boolean)
|
||||
for (let i = 0; i < hashes.length; i++) {
|
||||
const item = hashes[i]
|
||||
if (!item) continue
|
||||
hash = item.split('=')
|
||||
const keyRaw = hash[0] ?? ''
|
||||
const valueRaw = hash[1] ?? ''
|
||||
const key = decodeURIComponent(keyRaw)
|
||||
const value = decodeURIComponent(valueRaw)
|
||||
vars.push(key)
|
||||
vars[key] = value
|
||||
}
|
||||
return vars
|
||||
},
|
||||
getUrlVar(name: string): string | undefined {
|
||||
return ($ as any).getUrlVars()[name]
|
||||
},
|
||||
})
|
||||
|
||||
const LESSON_PREFIX = 'hsgrl'
|
||||
|
||||
const videoajax: VideoAjax = videoAjax()
|
||||
videoajax.setHost('/')
|
||||
|
||||
// 设置我的自定义数据(所有的自定义数据都设置在第一个课时ID上,以key来区分不同的类型)
|
||||
function setLtDefine(key: string | number, value: string): void {
|
||||
if (iscallyb) {
|
||||
setUserDefine(1, key, value)
|
||||
} else {
|
||||
sessionStorage.setItem(`${LESSON_PREFIX}_${key}`, value)
|
||||
}
|
||||
}
|
||||
|
||||
let mycstr9 = ''
|
||||
|
||||
// 获取定义数据(由于底层是异步接口,这里返回 Promise)
|
||||
async function getLtDefine(key: string | number): Promise<string> {
|
||||
if (iscallyb) {
|
||||
if (mycstr9 === '') {
|
||||
const all = await getUsersDefine(1, emykey)
|
||||
if (all === undefined || all === null || all === 'null' || all === '') {
|
||||
mycstr9 = getFutureDa(10)
|
||||
setLtDefine(emykey, mycstr9)
|
||||
} else {
|
||||
mycstr9 = all as string // 这里是 emykey,对应上面 getUsersDefine 的 string 分支
|
||||
}
|
||||
}
|
||||
const str = mycstr9 === undefined || mycstr9 === null || mycstr9 === 'null' ? '' : mycstr9
|
||||
getCurrentDa(str)
|
||||
const objitem = await getUserDefine(1, key)
|
||||
return objitem === undefined || objitem === null || objitem === 'null' ? '' : objitem
|
||||
} else {
|
||||
const itemvalue = sessionStorage.getItem(`${LESSON_PREFIX}_${key}`)
|
||||
return itemvalue === undefined || itemvalue === null || itemvalue === 'null' ? '' : itemvalue
|
||||
}
|
||||
}
|
||||
|
||||
// 设置课程笔记10002
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function setCourseNotepad(collect: string[]): void {
|
||||
// 保持和原逻辑一致:序列化为 JSON 存储
|
||||
setLtDefine(10002, $.toJSON(collect))
|
||||
}
|
||||
|
||||
// 获取课程笔记10002(异步)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function getCourseNotepad(): Promise<string[]> {
|
||||
const raw = await getLtDefine(10002)
|
||||
if (raw === undefined || raw === null || raw === '') {
|
||||
// 原逻辑:返回长度为 9 的空字符串数组
|
||||
return ['', '', '', '', '', '', '', '', '']
|
||||
}
|
||||
return $.parseJSON(raw) as string[]
|
||||
}
|
||||
|
||||
// lessonId(课时唯一ID)
|
||||
export function setUserDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number,
|
||||
value: string
|
||||
): void {
|
||||
const param: UserDefineParam = {
|
||||
lessonId: `${LESSON_PREFIX}_${lessonId}`,
|
||||
key,
|
||||
content: value,
|
||||
}
|
||||
videoajax.addUserDefine(param)
|
||||
}
|
||||
|
||||
// 内部:将回调形式封装为 Promise
|
||||
function getUserDefineAsyncInternal(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string> {
|
||||
const param: UserDefineParam = {
|
||||
lessonId: `${LESSON_PREFIX}_${lessonId}`,
|
||||
order: key,
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let content = ''
|
||||
videoajax.getUserDefineInfoByUser(param, (res) => {
|
||||
// 保留原有 console 行为
|
||||
console.log(res)
|
||||
if (res && res.code === 200) {
|
||||
const json = (res.data.value || []) as VideoAjaxResponseItem[]
|
||||
const contents = json[0]?.content || ''
|
||||
content = contents
|
||||
} else {
|
||||
content = ''
|
||||
}
|
||||
resolve(content)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Promise 版本:获取用户自定义数据
|
||||
export async function getUserDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string> {
|
||||
return getUserDefineAsyncInternal(lessonId, key)
|
||||
}
|
||||
|
||||
// 内部:获取【所有】用户自定义数据(Promise 封装)
|
||||
function getUsersDefineAsyncInternal(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string | VideoAjaxResponseItem[]> {
|
||||
const param: UserDefineParam = {
|
||||
lessonId: `${LESSON_PREFIX}_${lessonId}`,
|
||||
order: key,
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let content: string | VideoAjaxResponseItem[] = ''
|
||||
videoajax.getUserDefineInfo(param, (data) => {
|
||||
if (data && data.code === 200) {
|
||||
const json = (data.data.value || []) as VideoAjaxResponseItem[]
|
||||
if (json.length > 1) {
|
||||
if (key === emykey) {
|
||||
const mdate = new Date(
|
||||
Math.max.apply(
|
||||
null,
|
||||
json.map((item) => new Date(item.content || '').getTime())
|
||||
)
|
||||
)
|
||||
content = formatDateFromMilliseconds(mdate)
|
||||
} else {
|
||||
content = json
|
||||
}
|
||||
} else {
|
||||
content = json[0]?.content || ''
|
||||
}
|
||||
} else {
|
||||
content = ''
|
||||
}
|
||||
resolve(content)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Promise 版本:获取【所有】用户自定义数据
|
||||
export async function getUsersDefine(
|
||||
lessonId: string | number,
|
||||
key: string | number
|
||||
): Promise<string | VideoAjaxResponseItem[]> {
|
||||
return getUsersDefineAsyncInternal(lessonId, key)
|
||||
}
|
||||
|
||||
// 根据课时顺序号(所处课程的第几课时)更新对应易班平台上的每个环节进度(异步)
|
||||
export async function setCourseTimeProgress(order: number): Promise<void> {
|
||||
// var courseid = getCookie(lesson+"_course_id");//获取url链接的课程ID
|
||||
const courseid = await getLtDefine('10000')
|
||||
console.info(`courseid:${courseid} order:${order}`)
|
||||
if (iscallyb && courseid !== undefined && courseid !== null && courseid !== '') {
|
||||
if (order > 0) {
|
||||
const param2 = { order, co: courseid, process: 100 }
|
||||
videoajax.finishCourse(param2)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-29
@@ -1,56 +1,53 @@
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { type ClassValue, clsx } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs));
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
// 图片资源映射 - 使用静态导入确保构建时包含所有图片
|
||||
const imageModules = import.meta.glob(
|
||||
"../../assets/images/**/*.{png,jpg,jpeg,gif,svg,webp}",
|
||||
{
|
||||
eager: true,
|
||||
}
|
||||
);
|
||||
const imageModules = import.meta.glob('../../assets/images/**/*.{png,jpg,jpeg,gif,svg,webp}', {
|
||||
eager: true,
|
||||
})
|
||||
|
||||
//访问静态图片 - 使用静态导入确保构建后路径正确
|
||||
export const getStaticImage = (path: string) => {
|
||||
try {
|
||||
// 确保路径以正确的格式结尾
|
||||
const imagePath =
|
||||
path.endsWith(".png") ||
|
||||
path.endsWith(".jpg") ||
|
||||
path.endsWith(".jpeg") ||
|
||||
path.endsWith(".gif") ||
|
||||
path.endsWith(".svg") ||
|
||||
path.endsWith(".webp")
|
||||
path.endsWith('.png') ||
|
||||
path.endsWith('.jpg') ||
|
||||
path.endsWith('.jpeg') ||
|
||||
path.endsWith('.gif') ||
|
||||
path.endsWith('.svg') ||
|
||||
path.endsWith('.webp')
|
||||
? `../../assets/images/${path}`
|
||||
: `../../assets/images/${path}.png`;
|
||||
: `../../assets/images/${path}.png`
|
||||
|
||||
// 使用静态导入的模块
|
||||
const module = imageModules[imagePath];
|
||||
if (module && typeof module === "object" && "default" in module) {
|
||||
return module.default as string;
|
||||
const module = imageModules[imagePath]
|
||||
if (module && typeof module === 'object' && 'default' in module) {
|
||||
return module.default as string
|
||||
}
|
||||
|
||||
// 回退到URL方式
|
||||
return new URL(imagePath, import.meta.url).href;
|
||||
return new URL(imagePath, import.meta.url).href
|
||||
} catch (error) {
|
||||
console.error("Failed to load image:", path, error);
|
||||
return "";
|
||||
console.error('Failed to load image:', path, error)
|
||||
return ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 获取背景图片的专用函数
|
||||
export const getBackgroundImage = (path: string) => {
|
||||
const imageUrl = getStaticImage(path);
|
||||
return imageUrl ? `url(${imageUrl})` : "none";
|
||||
};
|
||||
const imageUrl = getStaticImage(path)
|
||||
return imageUrl ? `url(${imageUrl})` : 'none'
|
||||
}
|
||||
|
||||
// 获取 public 文件夹中的资源路径(用于 Word 文档等)
|
||||
export const getPublicPath = (path: string) => {
|
||||
// 移除开头的斜杠(如果有)
|
||||
const cleanPath = path.startsWith("/") ? path.slice(1) : path;
|
||||
const cleanPath = path.startsWith('/') ? path.slice(1) : path
|
||||
// 使用 Vite 的 BASE_URL 环境变量来处理基础路径
|
||||
return `${import.meta.env.BASE_URL}${cleanPath}`;
|
||||
};
|
||||
return `${import.meta.env.BASE_URL}${cleanPath}`
|
||||
}
|
||||
@@ -5,12 +5,12 @@
|
||||
|
||||
// 敏感词库(可根据实际需求扩展)
|
||||
const SENSITIVE_WORDS = [
|
||||
"敏感词1",
|
||||
"敏感词2",
|
||||
"测试",
|
||||
"垃圾",
|
||||
'敏感词1',
|
||||
'敏感词2',
|
||||
'测试',
|
||||
'垃圾',
|
||||
// 可以根据实际需求添加更多敏感词
|
||||
];
|
||||
]
|
||||
|
||||
/**
|
||||
* 检查文本中是否包含敏感词
|
||||
@@ -18,13 +18,11 @@ const SENSITIVE_WORDS = [
|
||||
* @returns 是否包含敏感词
|
||||
*/
|
||||
export function containsSensitiveWord(text: string): boolean {
|
||||
if (!text) return false;
|
||||
if (!text) return false
|
||||
|
||||
const normalizedText = text.toLowerCase().trim();
|
||||
const normalizedText = text.toLowerCase().trim()
|
||||
|
||||
return SENSITIVE_WORDS.some((word) =>
|
||||
normalizedText.includes(word.toLowerCase())
|
||||
);
|
||||
return SENSITIVE_WORDS.some((word) => normalizedText.includes(word.toLowerCase()))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,16 +31,16 @@ export function containsSensitiveWord(text: string): boolean {
|
||||
* @returns 处理后的文本
|
||||
*/
|
||||
export function filterSensitiveWords(text: string): string {
|
||||
if (!text) return text;
|
||||
if (!text) return text
|
||||
|
||||
let result = text;
|
||||
let result = text
|
||||
|
||||
SENSITIVE_WORDS.forEach((word) => {
|
||||
const regex = new RegExp(word, "gi");
|
||||
result = result.replace(regex, "*".repeat(word.length));
|
||||
});
|
||||
const regex = new RegExp(word, 'gi')
|
||||
result = result.replace(regex, '*'.repeat(word.length))
|
||||
})
|
||||
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,10 +49,10 @@ export function filterSensitiveWords(text: string): string {
|
||||
* @returns 过滤后的内容
|
||||
*/
|
||||
export function filterInput(input: string): string {
|
||||
if (!input) return input;
|
||||
if (!input) return input
|
||||
|
||||
// 先进行敏感词过滤
|
||||
const filtered = filterSensitiveWords(input);
|
||||
const filtered = filterSensitiveWords(input)
|
||||
|
||||
return filtered;
|
||||
return filtered
|
||||
}
|
||||
Reference in new issue
Block a user