|
@@ -727,7 +727,13 @@ import { ElMessage } from "element-plus";
|
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
import type { FormInstance, FormRules } from "element-plus";
|
|
|
import type { UploadRequestOptions, UploadUserFile } from "element-plus";
|
|
import type { UploadRequestOptions, UploadUserFile } from "element-plus";
|
|
|
import { Plus, InfoFilled } from "@element-plus/icons-vue";
|
|
import { Plus, InfoFilled } from "@element-plus/icons-vue";
|
|
|
-import { getOcrRequestByBase64, uploadAlipayImage } from "@/api/modules/businessInfo";
|
|
|
|
|
|
|
+import { getOcrRequestByBase64 } from "@/api/modules/businessInfo";
|
|
|
|
|
+import {
|
|
|
|
|
+ uploadBusinessInfoImageToOss,
|
|
|
|
|
+ uploadBusinessInfoImageWithPageOcr,
|
|
|
|
|
+ filterOutUploadUserFileByUid,
|
|
|
|
|
+ failBusinessInfoUploadCleanup
|
|
|
|
|
+} from "@/utils/businessInfoImageUpload";
|
|
|
import { localGet, localSet } from "@/utils/index";
|
|
import { localGet, localSet } from "@/utils/index";
|
|
|
import cityJson from "@/assets/json/city.json";
|
|
import cityJson from "@/assets/json/city.json";
|
|
|
import categoryJson from "@/views/businessInfo/category.json";
|
|
import categoryJson from "@/views/businessInfo/category.json";
|
|
@@ -1456,21 +1462,19 @@ async function runOcrAfterZfbUpload(kind: UploadKind, file: File) {
|
|
|
formData.append("imageFile", file, file.name || "license.jpg");
|
|
formData.append("imageFile", file, file.name || "license.jpg");
|
|
|
formData.append("ocrType", "BUSINESS_LICENSE");
|
|
formData.append("ocrType", "BUSINESS_LICENSE");
|
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
|
- if (isOcrSuccess(res)) {
|
|
|
|
|
- const fields = pickBusinessLicenseOcrFields(res);
|
|
|
|
|
- if (fields.creditCode) form.creditCode = fields.creditCode;
|
|
|
|
|
- if (form.subjectType === "07") {
|
|
|
|
|
- if (fields.companyName) {
|
|
|
|
|
- form.householdLicenseName = fields.companyName;
|
|
|
|
|
- form.merchantShortName = fields.companyName;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- if (fields.companyName) form.merchantShortName = fields.companyName;
|
|
|
|
|
- if (fields.legalPerson) form.legalName = fields.legalPerson;
|
|
|
|
|
|
|
+ if (!isOcrSuccess(res)) {
|
|
|
|
|
+ throw new Error(String(res?.msg || "营业执照识别未通过,请核对照片清晰度"));
|
|
|
|
|
+ }
|
|
|
|
|
+ const fields = pickBusinessLicenseOcrFields(res);
|
|
|
|
|
+ if (fields.creditCode) form.creditCode = fields.creditCode;
|
|
|
|
|
+ if (form.subjectType === "07") {
|
|
|
|
|
+ if (fields.companyName) {
|
|
|
|
|
+ form.householdLicenseName = fields.companyName;
|
|
|
|
|
+ form.merchantShortName = fields.companyName;
|
|
|
}
|
|
}
|
|
|
- ElMessage.success("营业执照识别成功");
|
|
|
|
|
} else {
|
|
} else {
|
|
|
- ElMessage.warning(res?.msg || "营业执照识别未通过,请核对照片清晰度");
|
|
|
|
|
|
|
+ if (fields.companyName) form.merchantShortName = fields.companyName;
|
|
|
|
|
+ if (fields.legalPerson) form.legalName = fields.legalPerson;
|
|
|
}
|
|
}
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -1479,14 +1483,12 @@ async function runOcrAfterZfbUpload(kind: UploadKind, file: File) {
|
|
|
formData.append("imageFile", file, file.name || "institution-cert.jpg");
|
|
formData.append("imageFile", file, file.name || "institution-cert.jpg");
|
|
|
formData.append("ocrType", "BUSINESS_LICENSE");
|
|
formData.append("ocrType", "BUSINESS_LICENSE");
|
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
|
- if (isOcrSuccess(res)) {
|
|
|
|
|
- const f = pickInstitutionCertOcrFields(res);
|
|
|
|
|
- if (f.certNumber) form.institutionCertNumber = f.certNumber;
|
|
|
|
|
- if (f.orgName) form.merchantShortName = f.orgName;
|
|
|
|
|
- ElMessage.success("事业单位法人证书识别成功");
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.warning(res?.msg || "事业单位法人证书识别未通过,请核对照片清晰度");
|
|
|
|
|
|
|
+ if (!isOcrSuccess(res)) {
|
|
|
|
|
+ throw new Error(String(res?.msg || "事业单位法人证书识别未通过,请核对照片清晰度"));
|
|
|
}
|
|
}
|
|
|
|
|
+ const f = pickInstitutionCertOcrFields(res);
|
|
|
|
|
+ if (f.certNumber) form.institutionCertNumber = f.certNumber;
|
|
|
|
|
+ if (f.orgName) form.merchantShortName = f.orgName;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
if (kind === "idFront") {
|
|
if (kind === "idFront") {
|
|
@@ -1494,16 +1496,14 @@ async function runOcrAfterZfbUpload(kind: UploadKind, file: File) {
|
|
|
formData.append("imageFile", file, file.name || "id-portrait.jpg");
|
|
formData.append("imageFile", file, file.name || "id-portrait.jpg");
|
|
|
formData.append("ocrType", "ID_CARD");
|
|
formData.append("ocrType", "ID_CARD");
|
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
|
- if (isOcrSuccess(res)) {
|
|
|
|
|
- const f = pickIdCardPortraitOcrFields(res);
|
|
|
|
|
- if (f.name) form.legalName = f.name;
|
|
|
|
|
- if (f.idNumber) form.idNumber = f.idNumber;
|
|
|
|
|
- if (f.cardPeriodBegin && f.cardPeriodEnd) {
|
|
|
|
|
- form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
|
|
|
|
|
- }
|
|
|
|
|
- ElMessage.success("身份证人像面识别成功");
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.warning(res?.msg || "身份证人像面识别未通过,请核对照片清晰度");
|
|
|
|
|
|
|
+ if (!isOcrSuccess(res)) {
|
|
|
|
|
+ throw new Error(String(res?.msg || "身份证人像面识别未通过,请核对照片清晰度"));
|
|
|
|
|
+ }
|
|
|
|
|
+ const f = pickIdCardPortraitOcrFields(res);
|
|
|
|
|
+ if (f.name) form.legalName = f.name;
|
|
|
|
|
+ if (f.idNumber) form.idNumber = f.idNumber;
|
|
|
|
|
+ if (f.cardPeriodBegin && f.cardPeriodEnd) {
|
|
|
|
|
+ form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
|
|
|
}
|
|
}
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -1512,18 +1512,14 @@ async function runOcrAfterZfbUpload(kind: UploadKind, file: File) {
|
|
|
formData.append("imageFile", file, file.name || "id-emblem.jpg");
|
|
formData.append("imageFile", file, file.name || "id-emblem.jpg");
|
|
|
formData.append("ocrType", "ID_CARD");
|
|
formData.append("ocrType", "ID_CARD");
|
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
const res: any = await getOcrRequestByBase64(formData);
|
|
|
- if (isOcrSuccess(res)) {
|
|
|
|
|
- const f = pickIdCardPortraitOcrFields(res);
|
|
|
|
|
- if (f.cardPeriodBegin && f.cardPeriodEnd) {
|
|
|
|
|
- form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
|
|
|
|
|
- }
|
|
|
|
|
- if (f.cardPeriodBegin || f.cardPeriodEnd) {
|
|
|
|
|
- ElMessage.success("身份证国徽面识别成功");
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.warning("未识别到有效期限,请确认国徽面照片清晰完整");
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.warning(res?.msg || "身份证国徽面识别未通过,请核对照片清晰度");
|
|
|
|
|
|
|
+ if (!isOcrSuccess(res)) {
|
|
|
|
|
+ throw new Error(String(res?.msg || "身份证国徽面识别未通过,请核对照片清晰度"));
|
|
|
|
|
+ }
|
|
|
|
|
+ const f = pickIdCardPortraitOcrFields(res);
|
|
|
|
|
+ if (f.cardPeriodBegin && f.cardPeriodEnd) {
|
|
|
|
|
+ form.businessTermRange = [f.cardPeriodBegin, f.cardPeriodEnd];
|
|
|
|
|
+ } else if (!f.cardPeriodBegin && !f.cardPeriodEnd) {
|
|
|
|
|
+ throw new Error("未识别到有效期限,请确认国徽面照片清晰完整");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1543,102 +1539,122 @@ function urlFieldFor(kind: UploadKind): keyof typeof form {
|
|
|
return map[kind];
|
|
return map[kind];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function fileListForUploadKind(kind: UploadKind): UploadUserFile[] {
|
|
|
|
|
+ const map: Record<UploadKind, UploadUserFile[]> = {
|
|
|
|
|
+ license: form.licenseFileList,
|
|
|
|
|
+ idFront: form.idFrontFileList,
|
|
|
|
|
+ idBack: form.idBackFileList,
|
|
|
|
|
+ storefront: form.storefrontFileList,
|
|
|
|
|
+ interior: form.interiorFileList,
|
|
|
|
|
+ institutionCert: form.institutionCertFileList,
|
|
|
|
|
+ otherOrgCert: form.otherOrgCertFileList,
|
|
|
|
|
+ socialCert: form.socialCertFileList,
|
|
|
|
|
+ govCert: form.govCertFileList
|
|
|
|
|
+ };
|
|
|
|
|
+ return map[kind] ?? [];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function setFileListForUploadKind(kind: UploadKind, list: UploadUserFile[]) {
|
|
|
|
|
+ if (kind === "license") form.licenseFileList = list;
|
|
|
|
|
+ else if (kind === "idFront") form.idFrontFileList = list;
|
|
|
|
|
+ else if (kind === "idBack") form.idBackFileList = list;
|
|
|
|
|
+ else if (kind === "storefront") form.storefrontFileList = list;
|
|
|
|
|
+ else if (kind === "interior") form.interiorFileList = list;
|
|
|
|
|
+ else if (kind === "institutionCert") form.institutionCertFileList = list;
|
|
|
|
|
+ else if (kind === "otherOrgCert") form.otherOrgCertFileList = list;
|
|
|
|
|
+ else if (kind === "socialCert") form.socialCertFileList = list;
|
|
|
|
|
+ else if (kind === "govCert") form.govCertFileList = list;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function handleSingleUpload(options: UploadRequestOptions, kind: UploadKind) {
|
|
async function handleSingleUpload(options: UploadRequestOptions, kind: UploadKind) {
|
|
|
const uploadFileItem = options.file as UploadUserFile;
|
|
const uploadFileItem = options.file as UploadUserFile;
|
|
|
|
|
+ const uid = uploadFileItem.uid;
|
|
|
const raw = uploadFileItem.raw || uploadFileItem;
|
|
const raw = uploadFileItem.raw || uploadFileItem;
|
|
|
const file = raw instanceof File ? raw : null;
|
|
const file = raw instanceof File ? raw : null;
|
|
|
- if (!file) return;
|
|
|
|
|
-
|
|
|
|
|
const field = urlFieldFor(kind);
|
|
const field = urlFieldFor(kind);
|
|
|
|
|
+
|
|
|
|
|
+ if (!file) {
|
|
|
|
|
+ setFileListForUploadKind(kind, filterOutUploadUserFileByUid(fileListForUploadKind(kind), uid));
|
|
|
|
|
+ options.onError(new Error("无效文件") as any);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
uploadFileItem.status = "uploading";
|
|
uploadFileItem.status = "uploading";
|
|
|
try {
|
|
try {
|
|
|
if (file.size > MAX_ALIPAY_IMAGE_BYTES) {
|
|
if (file.size > MAX_ALIPAY_IMAGE_BYTES) {
|
|
|
- uploadFileItem.status = "fail";
|
|
|
|
|
|
|
+ setFileListForUploadKind(kind, filterOutUploadUserFileByUid(fileListForUploadKind(kind), uid));
|
|
|
ElMessage.error("文件大小不能超过 20M");
|
|
ElMessage.error("文件大小不能超过 20M");
|
|
|
|
|
+ options.onError(new Error("文件大小不能超过 20M") as any);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- const imageType = resolveAlipayImageType(file);
|
|
|
|
|
- if (!imageType) {
|
|
|
|
|
- uploadFileItem.status = "fail";
|
|
|
|
|
- ElMessage.error("无法识别图片格式,请使用带扩展名的文件(如 .jpg、.png)");
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ const needOcr = kind === "license" || kind === "idFront" || kind === "idBack" || kind === "institutionCert";
|
|
|
|
|
+ const { fileUrl } = needOcr
|
|
|
|
|
+ ? await uploadBusinessInfoImageWithPageOcr(file, f => runOcrAfterZfbUpload(kind, f), {
|
|
|
|
|
+ showUploadOverlay: true
|
|
|
|
|
+ })
|
|
|
|
|
+ : await uploadBusinessInfoImageToOss(file, { showUploadOverlay: true });
|
|
|
|
|
+ const resolvedImageId = extractAlipayFilenameFromImageUrl(fileUrl) || fileUrl;
|
|
|
|
|
+
|
|
|
|
|
+ if (needOcr) {
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ const f = formRef.value;
|
|
|
|
|
+ if (!f) return;
|
|
|
|
|
+ if (kind === "license") {
|
|
|
|
|
+ f.validateField("creditCode").catch(() => {});
|
|
|
|
|
+ f.validateField("merchantShortName").catch(() => {});
|
|
|
|
|
+ if (form.subjectType === "07") {
|
|
|
|
|
+ f.validateField("householdLicenseName").catch(() => {});
|
|
|
|
|
+ } else {
|
|
|
|
|
+ f.validateField("legalName").catch(() => {});
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (kind === "institutionCert") {
|
|
|
|
|
+ f.validateField("institutionCertNumber").catch(() => {});
|
|
|
|
|
+ f.validateField("merchantShortName").catch(() => {});
|
|
|
|
|
+ } else if (kind === "idFront") {
|
|
|
|
|
+ f.validateField("legalName").catch(() => {});
|
|
|
|
|
+ f.validateField("idNumber").catch(() => {});
|
|
|
|
|
+ f.validateField("businessTermRange").catch(() => {});
|
|
|
|
|
+ } else if (kind === "idBack") {
|
|
|
|
|
+ f.validateField("businessTermRange").catch(() => {});
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
- const storeId = resolveAlipayUploadStoreId();
|
|
|
|
|
- // if (storeId === null) {
|
|
|
|
|
- // uploadFileItem.status = "fail";
|
|
|
|
|
- // ElMessage.error("未获取到门店 storeId,请重新登录或通过链接传入 storeId");
|
|
|
|
|
- // return;
|
|
|
|
|
- // }
|
|
|
|
|
- const res: any = await uploadAlipayImage({
|
|
|
|
|
- storeId,
|
|
|
|
|
- imageType,
|
|
|
|
|
- imageContent: file
|
|
|
|
|
- });
|
|
|
|
|
- const { fileUrl, mediaId, errMsg } = parseMediaUploadResult(res);
|
|
|
|
|
- const httpOk = isAlipayUploadHttpSuccess(res);
|
|
|
|
|
- const hasMediaRef = !!(fileUrl || mediaId);
|
|
|
|
|
- const resolvedImageId = resolveAlipayUploadImageId(res, fileUrl, mediaId);
|
|
|
|
|
-
|
|
|
|
|
- if (hasMediaRef || httpOk) {
|
|
|
|
|
- uploadFileItem.status = "success";
|
|
|
|
|
- if (fileUrl) {
|
|
|
|
|
- uploadFileItem.url = fileUrl;
|
|
|
|
|
- } else {
|
|
|
|
|
- uploadFileItem.url = URL.createObjectURL(file);
|
|
|
|
|
- }
|
|
|
|
|
- uploadFileItem.response = { media_id: resolvedImageId, url: fileUrl };
|
|
|
|
|
- (form as any)[field] = fileUrl || mediaId || (httpOk ? uploadFileItem.url : "");
|
|
|
|
|
- if (kind === "storefront") {
|
|
|
|
|
- form.storefrontImageId = resolvedImageId;
|
|
|
|
|
- }
|
|
|
|
|
- if (kind === "interior") {
|
|
|
|
|
- form.interiorImageId = resolvedImageId;
|
|
|
|
|
- }
|
|
|
|
|
- if (kind === "license") {
|
|
|
|
|
- form.licenseImageId = resolvedImageId;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- const needOcr = kind === "license" || kind === "idFront" || kind === "idBack" || kind === "institutionCert";
|
|
|
|
|
- if (needOcr) {
|
|
|
|
|
- try {
|
|
|
|
|
- await runOcrAfterZfbUpload(kind, file);
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- const f = formRef.value;
|
|
|
|
|
- if (!f) return;
|
|
|
|
|
- if (kind === "license") {
|
|
|
|
|
- f.validateField("creditCode").catch(() => {});
|
|
|
|
|
- f.validateField("merchantShortName").catch(() => {});
|
|
|
|
|
- if (form.subjectType === "07") {
|
|
|
|
|
- f.validateField("householdLicenseName").catch(() => {});
|
|
|
|
|
- } else {
|
|
|
|
|
- f.validateField("legalName").catch(() => {});
|
|
|
|
|
- }
|
|
|
|
|
- } else if (kind === "institutionCert") {
|
|
|
|
|
- f.validateField("institutionCertNumber").catch(() => {});
|
|
|
|
|
- f.validateField("merchantShortName").catch(() => {});
|
|
|
|
|
- } else if (kind === "idFront") {
|
|
|
|
|
- f.validateField("legalName").catch(() => {});
|
|
|
|
|
- f.validateField("idNumber").catch(() => {});
|
|
|
|
|
- f.validateField("businessTermRange").catch(() => {});
|
|
|
|
|
- } else if (kind === "idBack") {
|
|
|
|
|
- f.validateField("businessTermRange").catch(() => {});
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- } catch {
|
|
|
|
|
- ElMessage.warning("识别服务暂时不可用,请稍后重试或手动填写");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- uploadFileItem.status = "fail";
|
|
|
|
|
- ElMessage.error(errMsg || res?.msg || "上传失败,未返回可用结果");
|
|
|
|
|
|
|
+ uploadFileItem.status = "success";
|
|
|
|
|
+ uploadFileItem.url = fileUrl;
|
|
|
|
|
+ uploadFileItem.response = { media_id: resolvedImageId, url: fileUrl };
|
|
|
|
|
+ (form as any)[field] = fileUrl;
|
|
|
|
|
+ if (kind === "storefront") {
|
|
|
|
|
+ form.storefrontImageId = resolvedImageId;
|
|
|
}
|
|
}
|
|
|
- } catch {
|
|
|
|
|
- uploadFileItem.status = "fail";
|
|
|
|
|
- ElMessage.error("上传失败,请稍后重试");
|
|
|
|
|
|
|
+ if (kind === "interior") {
|
|
|
|
|
+ form.interiorImageId = resolvedImageId;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (kind === "license") {
|
|
|
|
|
+ form.licenseImageId = resolvedImageId;
|
|
|
|
|
+ }
|
|
|
|
|
+ options.onSuccess({ url: fileUrl } as any);
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ failBusinessInfoUploadCleanup({
|
|
|
|
|
+ fileList: fileListForUploadKind(kind),
|
|
|
|
|
+ setFileList: list => setFileListForUploadKind(kind, list),
|
|
|
|
|
+ uid,
|
|
|
|
|
+ onClear: () => clearZfbUploadFieldsForKind(kind),
|
|
|
|
|
+ error: err
|
|
|
|
|
+ });
|
|
|
|
|
+ options.onError(err as any);
|
|
|
}
|
|
}
|
|
|
formRef.value?.validateField(field as string).catch(() => {});
|
|
formRef.value?.validateField(field as string).catch(() => {});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function clearZfbUploadFieldsForKind(kind: UploadKind) {
|
|
|
|
|
+ const field = urlFieldFor(kind);
|
|
|
|
|
+ (form as any)[field] = "";
|
|
|
|
|
+ if (kind === "storefront") form.storefrontImageId = "";
|
|
|
|
|
+ if (kind === "interior") form.interiorImageId = "";
|
|
|
|
|
+ if (kind === "license") form.licenseImageId = "";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function onSingleRemove(fileList: UploadUserFile[], kind: UploadKind) {
|
|
function onSingleRemove(fileList: UploadUserFile[], kind: UploadKind) {
|
|
|
const field = urlFieldFor(kind);
|
|
const field = urlFieldFor(kind);
|
|
|
if (!fileList.length) {
|
|
if (!fileList.length) {
|
|
@@ -1712,10 +1728,13 @@ function buildBusinessAddressForAlipayJson():
|
|
|
return { address, districtCode, cityCode, provinceCode };
|
|
return { address, districtCode, cityCode, provinceCode };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/** 仅使用上传成功接口里保存的 image_id;且只认 .jpg / .jpeg / .png(不从 URL 等其它字段截取) */
|
|
|
|
|
|
|
+/** 进件用图片标识:支付宝 image_id 或 OSS 地址中的文件名(*.jpg / *.png) */
|
|
|
function alipayImageIdFromUploadOnly(imageIdField: string): string {
|
|
function alipayImageIdFromUploadOnly(imageIdField: string): string {
|
|
|
const s = String(imageIdField || "").trim();
|
|
const s = String(imageIdField || "").trim();
|
|
|
if (!s) return "";
|
|
if (!s) return "";
|
|
|
|
|
+ if (/^https?:\/\//i.test(s)) {
|
|
|
|
|
+ return extractAlipayFilenameFromImageUrl(s) || "";
|
|
|
|
|
+ }
|
|
|
const lower = s.toLowerCase();
|
|
const lower = s.toLowerCase();
|
|
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg") || lower.endsWith(".png")) return s;
|
|
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg") || lower.endsWith(".png")) return s;
|
|
|
return "";
|
|
return "";
|