@@ -86,26 +86,36 @@ const dragover = ref(false);
8686const error = ref (" " );
8787const previewUrl = ref (" " );
8888
89- // 初始化回显逻辑
89+ const getFullImageUrl = (path ) => {
90+ if (! path) return ' ' ;
91+
92+ // 1. 如果已经是完整的 http 链接,直接用
93+ if (path .startsWith (' http' )) return path;
94+
95+ // 2. 如果是静态资源 (/uploads 开头),直接拼域名前缀,不要拼 /api
96+ // 结果会是: https://myshkin451.com/uploads/posts/xxx.jpg
97+ if (path .startsWith (' /uploads' )) {
98+ return ` ${ window .location .origin }${ path} ` ;
99+ }
100+
101+ // 3. 其他情况才拼 API 地址
102+ const baseUrl = import .meta.env.VITE_API_URL || ' ' ;
103+ return ` ${ baseUrl}${ path} ` ;
104+ };
105+
106+ // 初始化回显
90107onMounted (() => {
91108 if (props .modelValue ) {
92- // 如果是完整 URL 直接用,如果是相对路径则拼上前缀
93- const isAbsolute = props .modelValue .startsWith (' http' );
94- // 注意:这里需要根据你的环境变量调整,如果没有定义 VITE_API_URL,默认用空或后端地址
95- const baseUrl = import .meta.env.VITE_API_URL || ' ' ;
96- previewUrl .value = isAbsolute ? props .modelValue : ` ${ baseUrl}${ props .modelValue } ` ;
109+ previewUrl .value = getFullImageUrl (props .modelValue );
97110 }
98111});
99112
100- // 监听外部 modelValue 变化(例如重置表单时)
113+ // 监听变化
101114watch (() => props .modelValue , (newVal ) => {
102115 if (! newVal) {
103116 previewUrl .value = " " ;
104117 } else if (newVal !== previewUrl .value ) {
105- // 只有当新值和当前预览不一致时才更新(避免循环)
106- const isAbsolute = newVal .startsWith (' http' );
107- const baseUrl = import .meta.env.VITE_API_URL || ' ' ;
108- previewUrl .value = isAbsolute ? newVal : ` ${ baseUrl}${ newVal} ` ;
118+ previewUrl .value = getFullImageUrl (newVal);
109119 }
110120});
111121
@@ -124,47 +134,35 @@ const onDrop = (e) => {
124134};
125135
126136const handleUpload = async (file ) => {
127- if (! file .type .startsWith (" image/" )) {
128- error .value = " File must be an image." ;
129- return ;
130- }
131- if (file .size > 5 * 1024 * 1024 ) {
132- error .value = " File size exceeds 5MB." ;
133- return ;
134- }
137+ // ... (保留你之前的校验逻辑) ...
138+ if (! file .type .startsWith (" image/" )) { error .value = " File must be an image." ; return ; }
139+ if (file .size > 20 * 1024 * 1024 ) { error .value = " File size exceeds 20MB." ; return ; } // 改成 20M 匹配服务器设置
135140
136- error .value = " " ;
137141 uploading .value = true ;
142+ error .value = " " ;
138143
139144 try {
140145 const fd = new FormData ();
141- // 根据你的 API 定义调整字段名
142146 const fieldName = props .uploadType === ' avatar' ? ' avatar' : ' image' ;
143147 fd .append (fieldName, file);
144148
145149 let res;
146150 if (props .uploadType === ' avatar' ) {
147151 res = await api .uploadAvatar (fd);
148152 } else {
149- // 默认使用通用的图片上传,返回 { url, path }
150153 res = await api .uploadPostImage (fd);
151154 }
152155
153- // 解析返回值:你的 API 返回 { url, path }
154- // url: 绝对路径 (用于预览)
155- // path: 相对路径 (用于存库)
156156 const { url , path } = res;
157-
158- // 更新预览
159- previewUrl .value = url;
160157
161- // 向父组件更新值 (通常存 path 到数据库比较灵活)
158+ // 更新预览 (使用 path 走一遍 getFullImageUrl 逻辑,或者直接用 url)
159+ previewUrl .value = url;
162160 emit (" update:modelValue" , path);
163161 emit (" upload-success" , url);
164162
165163 } catch (err) {
166164 console .error (err);
167- error .value = " Upload failed. Please try again. " ;
165+ error .value = " Upload failed." ;
168166 emit (" upload-error" , err);
169167 } finally {
170168 uploading .value = false ;
0 commit comments