搜索结果列表页面开发

This commit is contained in:
付民康
2025-03-12 18:41:20 +08:00
commit 7cebe8fc00
739 changed files with 88149 additions and 0 deletions

332
src/utils/hooks/useForm.ts Normal file
View File

@@ -0,0 +1,332 @@
import { computed, ref, reactive, shallowRef, onBeforeUnmount, watchEffect, nextTick } from 'vue';
import type { FormListProps } from '@/components/Form/types';
import type { Ref } from 'vue';
import { useRouter } from 'vue-router';
import { useAccount } from './useAccount';
import { Message } from 'vue-devui/message';
import { emitEvent } from '@/utils/eventBus';
export function useFormInteraction(currentForm: Ref<FormListProps[]>, flag: boolean = false, extraStatus: Ref<boolean> = ref(true)) {
const router = useRouter();
const { RecordInfo } = useAccount();
let interval: any = null;
const cacheForm = reactive<{ mobile: string, verificationcode: string, countdownSecond: number, user_id: string, mask: string }>({
mobile: '',
verificationcode: '',
countdownSecond: 59,
user_id: '',
mask: ''
});
// 表单错误信息
const formErrors = reactive<Record<string, string>>({});
// 额外验证参数
const extraErrors = reactive<{ agreement: string, requestInfo: string }>({
agreement: '',
requestInfo: ''
});
// 协议是否抖动
const AgreementWarn = ref(false);
// 禁用提交
const disabled = ref(true);
// 协议状态
const status = ref(flag);
// 表单ref
const FormRef = shallowRef<any>(null);
// 按钮loading
const loading = ref(false);
/** 密码框文字间距样式 */
const PasswordInputSpacing = computed(() => {
const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera;
const isIos = /iPad|iPhone|iPod/.test(userAgent) && !(window as any).MSStream;
return isIos ? '0px' : '-1px';
});
/** 当前表单错误信息 */
const errorMsg = computed(() => {
const keys = Object.keys(formErrors);
if (currentForm.value?.length) {
const obj = currentForm.value.find(item => keys.includes(item.key) && formErrors[item.key]);
if (FormRef.value) {
const filterKeys = keys.filter(key => key !== obj?.key && formErrors[key]);
filterKeys.length && FormRef.value?.ClearFormFields(filterKeys);
hackMsgError(obj?.key === 'verificationcode' || obj?.key === 'code');
}
if (obj) {
return formErrors[obj.key];
}
return extraErrors.agreement || extraErrors.requestInfo || '';
} else {
return extraErrors.agreement || extraErrors.requestInfo || '';
}
});
/** 设置表单单个字段校验信息 */
const setFormErrorKey = (conf: { errors: Record<string, any[]> } | Record<string, any>) => {
let message: string = '';
let key: string = '';
if (Object.prototype.hasOwnProperty.call(conf, 'errors')) {
const { errors } = conf;
key = Object.keys(errors)[0];
const formDict = errors[key];
message = formDict?.length ? formDict[0].message : '';
} else {
key = Object.keys(conf)[0];
message = (conf as Record<string, any>)[key];
}
formErrors[key] = message;
};
/** 捕获整个表单校验信息 */
const catchFormErrors = (conf: { errors: Record<string, any[]> }) => {
const { errors } = conf;
for (const key in errors) {
const obj: Record<string, string> = {};
obj[key] = errors[key][0].message as string;
setFormErrorKey(obj);
}
};
/** 清空表单校验信息 */
const clearFormError = (key?: string) => {
if (key) {
formErrors[key] = '';
} else {
for (const key in formErrors) {
formErrors[key] = '';
}
for (const key in extraErrors) {
extraErrors[key as keyof typeof extraErrors] = '';
}
}
};
/** 表单字段change事件 */
const handleFormChange = (conf: { key: string, errors: Record<string, any> | null, source: Record<string, any> }) => {
const { key, errors } = conf;
if (errors) {
setFormErrorKey({ errors });
} else {
formErrors[key] = '';
}
nextTick(() => {
const keys = Object.keys(formErrors);
if (currentForm.value?.length) {
const obj = currentForm.value.find(item => keys.includes(item.key) && formErrors[item.key]);
if (FormRef.value) {
const filterKeys = keys.filter(k => k !== obj?.key && formErrors[k]);
if (filterKeys.length) {
FormRef.value?.ClearFormFields(filterKeys);
} else {
obj && !errors && FormRef.value?.ValidateFormKeys([obj.key]);
}
}
hackMsgError(obj?.key === 'verificationcode' || obj?.key === 'code');
}
});
};
/** 表单input事件 */
const handleFormInput = (val: boolean) => {
disabled.value = val;
};
/** 第三方登录 */
const handleAuthLogin = (type: 'csdn' | 'gitee' | 'github' | 'mobile', callback?: Function, returnUrl? :string) => {
if (localStorage.getItem('access_token')) {
callback?.();
} else {
if (type === 'mobile') {
if (returnUrl) {
router.push('/loginByPhone?returnUrl=' + returnUrl);
} else {
router.push('/loginByPhone');
}
} else {
if (!status.value) {
extraErrors.agreement = `请阅读并同意用户协议以及其隐私政策`;
AgreementWarn.value = true;
setTimeout(() => {
AgreementWarn.value = false;
}, 500);
return;
}
if (localStorage.getItem('utm_source')) {
localStorage.removeItem('utm_source');
}
// 保存登录前页面地址
localStorage.setItem('loginReturnUrl', returnUrl || '');
// window.location.href = 'http://localhost:5173/oauth/callback';
const url = `${(import.meta as any).env.VITE_API_HOST}${(import.meta as any).env.VITE_PASSPORT_PREFIX || ''}/api/v1/oauth/login/${type}`;
window.location.href = url;
}
}
};
/** 提交表单 */
const handleSubmit = async(callback: (config: Record<string, any>) => Promise<void>, extraInfo: string = '') => {
if (!status.value) {
extraErrors.agreement = extraInfo || '请阅读并同意用户协议以及隐私政策';
AgreementWarn.value = true;
setTimeout(() => {
AgreementWarn.value = false;
}, 500);
return;
}
extraErrors.agreement = '';
if (FormRef.value) {
const formData = await FormRef.value.ValidateForm();
if (formData.type === 'success') {
loading.value = true;
clearFormError();
await callback(formData.forms);
setTimeout(() => {
loading.value = false;
}, 500);
} else {
catchFormErrors(formData);
}
}
};
/** 倒计时 */
const handleCountDown = async(conf: { key: string, value: any, sourceKey: string }, callback: () => Promise<boolean>) => {
const formData = await FormRef.value.ValidateFormKeys([conf.key]);
if (formData.type === 'success') {
clearFormError(conf.key);
const status = await callback();
status && resetMsgStatus(conf.sourceKey);
} else {
setFormErrorKey(formData);
}
};
/** gitcode 外链url */
const links = {
'agreement': 'https://gitcode.com/Gitcode-offical-team/GitCode-Docs/blob/main/%E7%94%A8%E6%88%B7%E5%8D%8F%E8%AE%AE%2F%E6%9C%8D%E5%8A%A1%E6%9D%A1%E6%AC%BE.md',
'privacy': 'https://gitcode.com/Gitcode-offical-team/GitCode-Docs/blob/main/%E7%94%A8%E6%88%B7%E5%8D%8F%E8%AE%AE%2F%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96.md'
};
/** 华为云 外链url */
const links_hw = {
agreement: 'https://www.huaweicloud.com/declaration/sa_cua.html',
privacy: 'https://www.huaweicloud.com/declaration/sa_prp.html'
};
/** 展示声明 */
const handleDisplay = (type: 'agreement' | 'privacy', class_type: 'gitcode' | 'hw' = 'gitcode') => {
const link = class_type === 'gitcode' ? links[type] : links_hw[type];
window.open(link);
};
/** 重置短信按钮状态 */
const resetMsgStatus = (key: string, status: boolean = true) => {
if (currentForm.value?.length) {
currentForm.value.forEach(item => {
if (item.key === key) {
if (item.props) {
item.props.countdown = status;
}
}
});
status && toCountDown(key);
}
};
/** 缓存倒计时间 */
const toCountDown = (key: string) => {
if (!interval) {
if (cacheForm.countdownSecond === 0) {
cacheForm.countdownSecond = 59;
}
interval = setInterval(() => {
if (cacheForm.countdownSecond >= 1) {
cacheForm.countdownSecond -= 1;
} else {
if (localStorage.getItem('cache_countdown')) {
localStorage.removeItem('cache_countdown');
}
cacheForm.countdownSecond = 59;
interval && clearInterval(interval);
interval = null;
resetMsgStatus(key, false);
}
}, 1000);
}
};
/** 存贮用户信息以及跳转 */
const saveUserInfo = (conf: any, returnUrl?: any) => {
const { username, email } = conf;
RecordInfo(conf);
Message.success({
message: '欢迎来到Gitcode!',
onClose: () => {
emitEvent('notice');
}
});
if (`${username}@gitcode.com` === email) { // 需要修改默认邮箱的弹窗
localStorage.setItem('validator_email', 'invalid');
} else {
localStorage.setItem('validator_email', 'valid');
}
if (returnUrl) {
location.href = returnUrl;
} else {
router.replace('/');
}
};
/**
* redirect绑定华为云
* @deprecated
*/
const redirectBind = (config: { user_id: string, mask: string, mobile: string }) => {
for (const key in config) {
cacheForm[key as keyof typeof config] = config[key as keyof typeof config];
}
// router.replace({
// path: '/bindPhone',
// query: config
// });
};
/** hack短信弹窗错误样式 */
const hackMsgError = (show_error: boolean) => {
const el = document.querySelector('.g-input-button');
if (el) {
if (show_error) {
(el as HTMLElement).style.borderColor = 'var(--devui-danger-line, #f66f6a)';
} else {
(el as HTMLElement).style.borderColor = 'rgba(230, 230, 232, 1)';
}
}
};
watchEffect(() => {
if (status.value && extraStatus.value && extraErrors.agreement) {
extraErrors.agreement = '';
}
});
onBeforeUnmount(() => {
if (interval) {
clearInterval(interval);
}
hackMsgError(false);
});
return {
AgreementWarn,
status,
disabled,
FormRef,
cacheForm,
formErrors,
PasswordInputSpacing,
extraErrors,
errorMsg,
loading,
setFormErrorKey,
catchFormErrors,
clearFormError,
toCountDown,
handleFormChange,
handleFormInput,
handleAuthLogin,
handleCountDown,
handleDisplay,
handleSubmit,
saveUserInfo
// redirectBind
};
}