Browse Source

分页刷新问题

master
zhanglei 1 day ago
parent
commit
0521c19267
  1. 84
      templates/vue/api.ts.j2
  2. 230
      templates/vue/index.vue.j2
  3. 217
      vue-vben-admin/apps/web-antd/src/views/device/index.vue
  4. 230
      vue-vben-admin/apps/web-antd/src/views/fun/index.vue

84
templates/vue/api.ts.j2

@ -9,46 +9,46 @@ import { useAccessStore } from '@vben/stores';
export namespace {{entity}}Api {
const applicationConfig = useAppConfig(import.meta.env, import.meta.env.PROD);
console.log('=== 接口域名 ===', applicationConfig.javaURL)
const applicationConfig = useAppConfig(import.meta.env, import.meta.env.PROD);
console.log('=== 接口域名 ===', applicationConfig.javaURL)
/**
* 分页查询
*/
export function page(params: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/page', params,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 分页查询
*/
export function page(params: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/page', params,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 获取详情
*/
export function get(id: number) {
return requestClient.get(applicationConfig.javaURL+'/{{old_table}}/' + id);
}
/**
* 获取详情
*/
export function get(id: number) {
return requestClient.get(applicationConfig.javaURL+'/{{old_table}}/' + id);
}
/**
* 新增
*/
export function add(data: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/add', data,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 新增
*/
export function add(data: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/add', data,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 修改
*/
export function save(data: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/modify', data,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 修改
*/
export function save(data: any) {
return requestClient.post(applicationConfig.javaURL+'/{{old_table}}/modify', data,
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 删除
*/
export function remove(id: number) {
return requestClient.delete(applicationConfig.javaURL+'/{{old_table}}/' + id);
}
/**
* 删除
*/
export function remove(id: number) {
return requestClient.delete(applicationConfig.javaURL+'/{{old_table}}/' + id);
}
/**
* 枚举列表
@ -58,12 +58,12 @@ export namespace {{entity}}Api {
{ headers: {'Content-Type': 'application/json', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 上传图片
*/
export function upload(params: any) {
return requestClient.post(applicationConfig.javaURL+'/file/up', params,
{ headers: {'Content-Type': 'multipart/form-data', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
/**
* 上传图片
*/
export function upload(params: any) {
return requestClient.post(applicationConfig.javaURL+'/file/up', params,
{ headers: {'Content-Type': 'multipart/form-data', Token: useAccessStore().accessToken, version: '1.0.1'}});
}
}

230
templates/vue/index.vue.j2

@ -18,7 +18,6 @@ const API_BASE_URL = import.meta.env.VITE_GLOB_API_URL || '';
const currentRow = ref(null);
const isEdit = ref(false);
const modalTitle = ref('新增');
const uploadVisible = ref(false);
const uploadFieldName = ref('');
const uploadImageUrl = ref('');
const uploadedUrl = ref(''); // 上传成功后返回的
@ -33,14 +32,12 @@ const enumData = reactive({
});
//todo 枚举数据在查询里面不展示的配置
const hiddenColumns = ref(['fun_code', 'graduallyIntervalTime', 'funMsgTitle', 'funImg', 'createdAt', 'updatedBy', 'updatedAt', 'userPassword', 'userId', 'userSys', 'deletedFlag', "userFace"])
const editFields = ['userId', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy', 'deletedFlag'];
const editFields = [{{editFields}}];
// ========== 判断是否是图片字段 ==========
function isImageField(fieldName: string): boolean {
const lowerName = fieldName.toLowerCase();
return lowerName.includes('img') || lowerName.includes('face') || lowerName.includes('picture');
function isImageField(field: string) {
return /img|face|picture/i.test(field);
}
// ========== 初始化枚举数据和查询表单 ==========
async function initEnumData() {
try {
@ -111,7 +108,6 @@ onMounted(() => {
initEnumData();
});
// ========== 查询表单配置 (初始为空 schema) ==========
const [QueryForm, queryFormApi] = useVbenForm({
schema: [], // 初始化为空数组
@ -134,9 +130,13 @@ watch(
{immediate: false}
);
// 存储当前页码
const currentPageRef = ref(1);
// ========== 表格配置 ==========
function getFullUrl(url: string) {
if (!url) return '';
if (url.startsWith('http')) return url;
return `${API_BASE_URL}${url}`;
}
const gridOptions = {
columns: [
...columns.map(col => {
@ -149,126 +149,27 @@ const gridOptions = {
slots: {
default: ({row}: any) => {
const imgUrl = row[col.field];
// 如果没有图片,显示提示文字
const handleClick = (e: Event) => {
e.stopPropagation();
currentRow.value = row;
isEdit.value = true;
openUploadDialog(col.field, imgUrl);
};
if (!imgUrl) {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
height: '50px',
}
}, [
h('span', {
style: {
color: '#999',
fontSize: '12px'
}
}, '无图片'),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
// 设置当前行数据
currentRow.value = row;
isEdit.value = true; // 设置为编辑模式
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '上传')
return h('div', { class: 'flex items-center justify-center gap-2 h-[50px]' }, [
h('span', { class: 'text-gray-400 text-xs' }, '无图片'),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '上传'),
]);
}
// 判断是否是完整的 URL
let fullUrl = imgUrl;
if (!imgUrl.startsWith('http://') && !imgUrl.startsWith('https://')) {
// 如果不是完整 URL,拼接基础 API 地址
const apiURL = import.meta.env.VITE_GLOB_API_URL || '';
fullUrl = `${apiURL}${imgUrl}`;
}
console.log('🖼️ 图片 URL:', fullUrl);
// 返回图片组件和上传按钮
try {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
}
}, [
h(Image, {
src: fullUrl,
height: 60,
width: 80,
preview: true,
style: {
borderRadius: '4px',
objectFit: 'cover',
cursor: 'pointer',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
onError: () => {
console.error('❌ 图片加载失败:', fullUrl);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#f5f5f5',
borderRadius: '4px',
color: '#999',
fontSize: '12px'
}
}, '加载失败');
}
}),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
// 设置当前行数据
currentRow.value = row;
isEdit.value = true; // 设置为编辑模式
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '更换')
]);
} catch (error) {
console.error('❌ 图片渲染错误:', error);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#fffbe6',
borderRadius: '4px',
color: '#faad14',
fontSize: '12px'
}
}, '渲染失败');
}
return h('div', { class: 'flex items-center gap-2 justify-center' }, [
h(Image, {
src: getFullUrl(imgUrl),
width: 80,
height: 60,
preview: true,
}),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '更换'),
]);
}
}
};
@ -289,14 +190,6 @@ const gridOptions = {
try {
// 获取查询表单的值
const queryValues = await queryFormApi.getValues();
console.log('=== 查询参数 ===', {
pageNum: page?.currentPage || 1,
pageSize: page?.pageSize || 10,
currentPageRef: currentPageRef.value,
...queryValues,
})
const res = await {{entity}}Api.page({
pageNum: page.currentPage || 1,
pageSize: page?.pageSize || 10,
@ -343,6 +236,7 @@ const [Modal, modalApi] = useVbenModal({
modalApi.close();
},
onConfirm: async () => {
let loadingMessage: any = null;
try {
const values = await formApi.validateAndSubmitForm();
if (!values) return;
@ -357,22 +251,31 @@ const [Modal, modalApi] = useVbenModal({
...submitValues,
userBirthday: submitValues.userBirthday ? dayjs(submitValues.userBirthday).format('YYYY-MM-DD') : null,
};
// 显示 loading 提示
loadingMessage = message.loading(isEdit.value ? '保存中...' : '新增中...', 0);
if (isEdit.value && currentRow.value?.id) {
await {{entity}}Api.save({...finalSubmitValues, id: currentRow.value.id});
Object.assign(currentRow.value, finalSubmitValues);
modalApi.close();
gridApi.reloadRow(currentRow.value);
loadingMessage();
isEdit.value = false;
message.success('保存成功!');
} else {
await {{entity}}Api.add(finalSubmitValues);
// 新增才 reload(必须)
modalApi.close();
gridApi.reload();
formUploadUrls.value = {};
loadingMessage();
message.success('新增成功!');
}
} catch (error) {
console.error('保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
}
},
onOpenChange(isOpen: boolean) {
@ -399,6 +302,7 @@ const [UploadModal, uploadModalApi] = useVbenModal({
uploadedUrl.value = '';
},
onConfirm: async () => {
let loadingMessage: any = null;
console.log('=== 点击确认保存 ===', {
uploadedUrl: uploadedUrl.value,
isEdit: isEdit.value,
@ -427,14 +331,15 @@ const [UploadModal, uploadModalApi] = useVbenModal({
id: currentRow.value.id
};
console.log('📤 提交保存数据:', submitData);
// 显示 loading 提示
loadingMessage = message.loading('保存图片中...', 0);
await {{entity}}Api.save(submitData);
message.success('保存成功!');
// 关闭弹窗并刷新表格
uploadModalApi.close();
// gridApi.reload();
loadingMessage()
// 重置状态
uploadFileList.value = [];
uploadedUrl.value = '';
@ -452,6 +357,9 @@ const [UploadModal, uploadModalApi] = useVbenModal({
} catch (error: any) {
console.error('❌ 保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
message.error(error?.message || '保存失败');
}
} else {
@ -497,13 +405,7 @@ const getEditFormSchema = () => {
console.log('📦 新增表单内上传文件:', file);
try {
const formData = new FormData();
formData.append('file', file);
// 调用上传 API
const res = await {{entity}}Api.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log(item.fieldName + ' 新增表单内上传成功,URL:', resultUrl);
message.success('上传成功!');
@ -545,6 +447,19 @@ const [Form, formApi] = useVbenForm({
},
})
// ========== 上传文件 ==========
async function uploadFile(file: File) {
let loadingMessage: any = null;
// 显示 loading 提示
loadingMessage = message.loading('图片上传中...', 0);
const formData = new FormData();
formData.append('file', file);
const res = await {{entity}}Api.upload(formData);
loadingMessage();
return res.result || res.message || res.url || res;
}
// ========== 打开上传对话框 ==========
function openUploadDialog(fieldName: string, currentUrl: string) {
console.log('=== 打开上传对话框 ===', {
@ -559,7 +474,6 @@ function openUploadDialog(fieldName: string, currentUrl: string) {
uploadImageUrl.value = currentUrl || '';
uploadedUrl.value = ''; // 重置上传后的 URL
uploadFileList.value = []; // 清空文件列表
uploadVisible.value = true;
uploadModalApi.open();
}
@ -575,17 +489,9 @@ async function handleCustomRequest(options: any) {
size: file.size,
lastModified: file.lastModified,
});
const formData = new FormData();
formData.append('file', file);
// 调用上传 API
const res = await {{entity}}Api.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log('✅ 上传成功,URL:', resultUrl);
message.success('上传成功!');
// 保存上传返回的 URL
uploadedUrl.value = resultUrl;
console.log('=== uploadedUrl 赋值后 ===', uploadedUrl.value);
@ -608,20 +514,6 @@ async function handleCustomRequest(options: any) {
}
}
// ========== 上传成功或失败后的处理
function handleChange(info: any) {
const {status} = info.file;
console.log('📋 文件状态变化:', status, info.file);
if (status === 'done') {
console.log('✅ 上传完成响应:', info);
} else if (status === 'error') {
console.error('❌ 上传失败:', info);
message.error(`${info.file.name} 上传失败`);
}
}
// ========== 打开新增弹窗 ==========
function handleAdd() {
isEdit.value = false;
@ -679,7 +571,6 @@ function handleReset() {
queryFormApi.resetForm();
gridApi.reload();
}
</script>
@ -728,7 +619,6 @@ function handleReset() {
<Form/>
</Modal>
<!-- 上传对话框 -->
<!-- 上传对话框 -->
<UploadModal>
<div style="padding: 20px;margin-top: 16px; text-align: center;">
<Upload
@ -769,7 +659,7 @@ function handleReset() {
<div v-if="uploadImageUrl && !uploadedUrl" style="margin-top: 16px; text-align: center;">
<p style="color: #999; font-size: 12px; margin-bottom: 8px;">当前图片:</p>
<Image
:src="uploadImageUrl.startsWith('http') || uploadImageUrl.startsWith('/') ? uploadImageUrl : `${API_BASE_URL}${uploadImageUrl}`"
:src="getFullUrl(uploadImageUrl)"
style="max-width: 200px; border-radius: 4px;"
:preview="true"
/>

217
vue-vben-admin/apps/web-antd/src/views/device/index.vue

@ -18,7 +18,6 @@ const API_BASE_URL = import.meta.env.VITE_GLOB_API_URL || '';
const currentRow = ref(null);
const isEdit = ref(false);
const modalTitle = ref('新增');
const uploadVisible = ref(false);
const uploadFieldName = ref('');
const uploadImageUrl = ref('');
const uploadedUrl = ref(''); //
@ -36,11 +35,9 @@ const hiddenColumns = ref(['fun_code', 'graduallyIntervalTime', 'funMsgTitle', '
const editFields = ['userId', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy', 'deletedFlag'];
// ========== ==========
function isImageField(fieldName: string): boolean {
const lowerName = fieldName.toLowerCase();
return lowerName.includes('img') || lowerName.includes('face') || lowerName.includes('picture');
function isImageField(field: string) {
return /img|face|picture/i.test(field);
}
// ========== ==========
async function initEnumData() {
try {
@ -111,7 +108,6 @@ onMounted(() => {
initEnumData();
});
// ========== ( schema) ==========
const [QueryForm, queryFormApi] = useVbenForm({
schema: [], //
@ -137,6 +133,11 @@ watch(
//
const currentPageRef = ref(1);
// ========== ==========
function getFullUrl(url: string) {
if (!url) return '';
if (url.startsWith('http')) return url;
return `${API_BASE_URL}${url}`;
}
const gridOptions = {
columns: [
...columns.map(col => {
@ -149,126 +150,27 @@ const gridOptions = {
slots: {
default: ({row}: any) => {
const imgUrl = row[col.field];
//
const handleClick = (e: Event) => {
e.stopPropagation();
currentRow.value = row;
isEdit.value = true;
openUploadDialog(col.field, imgUrl);
};
if (!imgUrl) {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
height: '50px',
}
}, [
h('span', {
style: {
color: '#999',
fontSize: '12px'
}
}, '无图片'),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
//
currentRow.value = row;
isEdit.value = true; //
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '上传')
]);
}
// URL
let fullUrl = imgUrl;
if (!imgUrl.startsWith('http://') && !imgUrl.startsWith('https://')) {
// URL API
const apiURL = import.meta.env.VITE_GLOB_API_URL || '';
fullUrl = `${apiURL}${imgUrl}`;
}
console.log('🖼️ 图片 URL:', fullUrl);
//
try {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
}
}, [
h(Image, {
src: fullUrl,
height: 60,
width: 80,
preview: true,
style: {
borderRadius: '4px',
objectFit: 'cover',
cursor: 'pointer',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
onError: () => {
console.error('❌ 图片加载失败:', fullUrl);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#f5f5f5',
borderRadius: '4px',
color: '#999',
fontSize: '12px'
}
}, '加载失败');
}
}),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
//
currentRow.value = row;
isEdit.value = true; //
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '更换')
return h('div', { class: 'flex items-center justify-center gap-2 h-[50px]' }, [
h('span', { class: 'text-gray-400 text-xs' }, '无图片'),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '上传'),
]);
} catch (error) {
console.error('❌ 图片渲染错误:', error);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#fffbe6',
borderRadius: '4px',
color: '#faad14',
fontSize: '12px'
}
}, '渲染失败');
}
return h('div', { class: 'flex items-center gap-2 justify-center' }, [
h(Image, {
src: getFullUrl(imgUrl),
width: 80,
height: 60,
preview: true,
}),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '更换'),
]);
}
}
};
@ -343,6 +245,7 @@ const [Modal, modalApi] = useVbenModal({
modalApi.close();
},
onConfirm: async () => {
let loadingMessage: any = null;
try {
const values = await formApi.validateAndSubmitForm();
if (!values) return;
@ -357,22 +260,31 @@ const [Modal, modalApi] = useVbenModal({
...submitValues,
userBirthday: submitValues.userBirthday ? dayjs(submitValues.userBirthday).format('YYYY-MM-DD') : null,
};
// loading
loadingMessage = message.loading(isEdit.value ? '保存中...' : '新增中...', 0);
if (isEdit.value && currentRow.value?.id) {
await deviceApi.save({...finalSubmitValues, id: currentRow.value.id});
Object.assign(currentRow.value, finalSubmitValues);
modalApi.close();
gridApi.reloadRow(currentRow.value);
loadingMessage();
isEdit.value = false;
message.success('保存成功!');
} else {
await deviceApi.add(finalSubmitValues);
// reload
modalApi.close();
gridApi.reload();
formUploadUrls.value = {};
loadingMessage();
message.success('新增成功!');
}
} catch (error) {
console.error('保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
}
},
onOpenChange(isOpen: boolean) {
@ -399,6 +311,7 @@ const [UploadModal, uploadModalApi] = useVbenModal({
uploadedUrl.value = '';
},
onConfirm: async () => {
let loadingMessage: any = null;
console.log('=== 点击确认保存 ===', {
uploadedUrl: uploadedUrl.value,
isEdit: isEdit.value,
@ -427,14 +340,15 @@ const [UploadModal, uploadModalApi] = useVbenModal({
id: currentRow.value.id
};
console.log('📤 提交保存数据:', submitData);
// loading
loadingMessage = message.loading('保存图片中...', 0);
await deviceApi.save(submitData);
message.success('保存成功!');
//
uploadModalApi.close();
// gridApi.reload();
loadingMessage()
//
uploadFileList.value = [];
uploadedUrl.value = '';
@ -452,6 +366,9 @@ const [UploadModal, uploadModalApi] = useVbenModal({
} catch (error: any) {
console.error('❌ 保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
message.error(error?.message || '保存失败');
}
} else {
@ -497,13 +414,7 @@ const getEditFormSchema = () => {
console.log('📦 新增表单内上传文件:', file);
try {
const formData = new FormData();
formData.append('file', file);
// API
const res = await deviceApi.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log(item.fieldName + ' 新增表单内上传成功,URL:', resultUrl);
message.success('上传成功!');
@ -545,6 +456,19 @@ const [Form, formApi] = useVbenForm({
},
})
// ========== ==========
async function uploadFile(file: File) {
let loadingMessage: any = null;
// loading
loadingMessage = message.loading('图片上传中...', 0);
const formData = new FormData();
formData.append('file', file);
const res = await deviceApi.upload(formData);
loadingMessage();
return res.result || res.message || res.url || res;
}
// ========== ==========
function openUploadDialog(fieldName: string, currentUrl: string) {
console.log('=== 打开上传对话框 ===', {
@ -559,7 +483,6 @@ function openUploadDialog(fieldName: string, currentUrl: string) {
uploadImageUrl.value = currentUrl || '';
uploadedUrl.value = ''; // URL
uploadFileList.value = []; //
uploadVisible.value = true;
uploadModalApi.open();
}
@ -575,17 +498,9 @@ async function handleCustomRequest(options: any) {
size: file.size,
lastModified: file.lastModified,
});
const formData = new FormData();
formData.append('file', file);
// API
const res = await deviceApi.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log('✅ 上传成功,URL:', resultUrl);
message.success('上传成功!');
// URL
uploadedUrl.value = resultUrl;
console.log('=== uploadedUrl 赋值后 ===', uploadedUrl.value);
@ -608,20 +523,6 @@ async function handleCustomRequest(options: any) {
}
}
// ==========
function handleChange(info: any) {
const {status} = info.file;
console.log('📋 文件状态变化:', status, info.file);
if (status === 'done') {
console.log('✅ 上传完成响应:', info);
} else if (status === 'error') {
console.error('❌ 上传失败:', info);
message.error(`${info.file.name} 上传失败`);
}
}
// ========== ==========
function handleAdd() {
isEdit.value = false;
@ -679,7 +580,6 @@ function handleReset() {
queryFormApi.resetForm();
gridApi.reload();
}
</script>
@ -728,7 +628,6 @@ function handleReset() {
<Form/>
</Modal>
<!-- 上传对话框 -->
<!-- 上传对话框 -->
<UploadModal>
<div style="padding: 20px;margin-top: 16px; text-align: center;">
<Upload
@ -769,7 +668,7 @@ function handleReset() {
<div v-if="uploadImageUrl && !uploadedUrl" style="margin-top: 16px; text-align: center;">
<p style="color: #999; font-size: 12px; margin-bottom: 8px;">当前图片:</p>
<Image
:src="uploadImageUrl.startsWith('http') || uploadImageUrl.startsWith('/') ? uploadImageUrl : `${API_BASE_URL}${uploadImageUrl}`"
:src="getFullUrl(uploadImageUrl)"
style="max-width: 200px; border-radius: 4px;"
:preview="true"
/>

230
vue-vben-admin/apps/web-antd/src/views/fun/index.vue

@ -18,7 +18,6 @@ const API_BASE_URL = import.meta.env.VITE_GLOB_API_URL || '';
const currentRow = ref(null);
const isEdit = ref(false);
const modalTitle = ref('新增');
const uploadVisible = ref(false);
const uploadFieldName = ref('');
const uploadImageUrl = ref('');
const uploadedUrl = ref(''); //
@ -33,14 +32,12 @@ const enumData = reactive({
});
//todo
const hiddenColumns = ref(['fun_code', 'graduallyIntervalTime', 'funMsgTitle', 'funImg', 'createdAt', 'updatedBy', 'updatedAt', 'userPassword', 'userId', 'userSys', 'deletedFlag', "userFace"])
const editFields = ['userId', 'createdAt', 'createdBy', 'updatedAt', 'updatedBy', 'deletedFlag'];
const editFields = ['userId','createdAt','createdBy','updatedAt','updatedBy','deletedFlag'];
// ========== ==========
function isImageField(fieldName: string): boolean {
const lowerName = fieldName.toLowerCase();
return lowerName.includes('img') || lowerName.includes('face') || lowerName.includes('picture');
function isImageField(field: string) {
return /img|face|picture/i.test(field);
}
// ========== ==========
async function initEnumData() {
try {
@ -111,7 +108,6 @@ onMounted(() => {
initEnumData();
});
// ========== ( schema) ==========
const [QueryForm, queryFormApi] = useVbenForm({
schema: [], //
@ -134,9 +130,13 @@ watch(
{immediate: false}
);
//
const currentPageRef = ref(1);
// ========== ==========
function getFullUrl(url: string) {
if (!url) return '';
if (url.startsWith('http')) return url;
return `${API_BASE_URL}${url}`;
}
const gridOptions = {
columns: [
...columns.map(col => {
@ -149,126 +149,27 @@ const gridOptions = {
slots: {
default: ({row}: any) => {
const imgUrl = row[col.field];
//
const handleClick = (e: Event) => {
e.stopPropagation();
currentRow.value = row;
isEdit.value = true;
openUploadDialog(col.field, imgUrl);
};
if (!imgUrl) {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
height: '50px',
}
}, [
h('span', {
style: {
color: '#999',
fontSize: '12px'
}
}, '无图片'),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
//
currentRow.value = row;
isEdit.value = true; //
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '上传')
return h('div', { class: 'flex items-center justify-center gap-2 h-[50px]' }, [
h('span', { class: 'text-gray-400 text-xs' }, '无图片'),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '上传'),
]);
}
// URL
let fullUrl = imgUrl;
if (!imgUrl.startsWith('http://') && !imgUrl.startsWith('https://')) {
// URL API
const apiURL = import.meta.env.VITE_GLOB_API_URL || '';
fullUrl = `${apiURL}${imgUrl}`;
}
console.log('🖼️ 图片 URL:', fullUrl);
//
try {
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
gap: '8px',
}
}, [
h(Image, {
src: fullUrl,
height: 60,
width: 80,
preview: true,
style: {
borderRadius: '4px',
objectFit: 'cover',
cursor: 'pointer',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
},
onError: () => {
console.error('❌ 图片加载失败:', fullUrl);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#f5f5f5',
borderRadius: '4px',
color: '#999',
fontSize: '12px'
}
}, '加载失败');
}
}),
h('button', {
onClick: (e: Event) => {
e.stopPropagation();
//
currentRow.value = row;
isEdit.value = true; //
openUploadDialog(col.field, imgUrl);
},
style: {
padding: '4px 8px',
fontSize: '12px',
color: '#1890ff',
backgroundColor: '#e6f7ff',
border: '1px solid #1890ff',
borderRadius: '4px',
cursor: 'pointer',
}
}, '更换')
]);
} catch (error) {
console.error('❌ 图片渲染错误:', error);
return h('div', {
style: {
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '50px',
backgroundColor: '#fffbe6',
borderRadius: '4px',
color: '#faad14',
fontSize: '12px'
}
}, '渲染失败');
}
return h('div', { class: 'flex items-center gap-2 justify-center' }, [
h(Image, {
src: getFullUrl(imgUrl),
width: 80,
height: 60,
preview: true,
}),
h('button', { onClick: handleClick, class: 'text-blue-500 text-xs' }, '更换'),
]);
}
}
};
@ -289,14 +190,6 @@ const gridOptions = {
try {
//
const queryValues = await queryFormApi.getValues();
console.log('=== 查询参数 ===', {
pageNum: page?.currentPage || 1,
pageSize: page?.pageSize || 10,
currentPageRef: currentPageRef.value,
...queryValues,
})
const res = await funApi.page({
pageNum: page.currentPage || 1,
pageSize: page?.pageSize || 10,
@ -343,6 +236,7 @@ const [Modal, modalApi] = useVbenModal({
modalApi.close();
},
onConfirm: async () => {
let loadingMessage: any = null;
try {
const values = await formApi.validateAndSubmitForm();
if (!values) return;
@ -357,22 +251,31 @@ const [Modal, modalApi] = useVbenModal({
...submitValues,
userBirthday: submitValues.userBirthday ? dayjs(submitValues.userBirthday).format('YYYY-MM-DD') : null,
};
// loading
loadingMessage = message.loading(isEdit.value ? '保存中...' : '新增中...', 0);
if (isEdit.value && currentRow.value?.id) {
await funApi.save({...finalSubmitValues, id: currentRow.value.id});
Object.assign(currentRow.value, finalSubmitValues);
modalApi.close();
gridApi.reloadRow(currentRow.value);
loadingMessage();
isEdit.value = false;
message.success('保存成功!');
} else {
await funApi.add(finalSubmitValues);
// reload
modalApi.close();
gridApi.reload();
formUploadUrls.value = {};
loadingMessage();
message.success('新增成功!');
}
} catch (error) {
console.error('保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
}
},
onOpenChange(isOpen: boolean) {
@ -399,6 +302,7 @@ const [UploadModal, uploadModalApi] = useVbenModal({
uploadedUrl.value = '';
},
onConfirm: async () => {
let loadingMessage: any = null;
console.log('=== 点击确认保存 ===', {
uploadedUrl: uploadedUrl.value,
isEdit: isEdit.value,
@ -427,14 +331,15 @@ const [UploadModal, uploadModalApi] = useVbenModal({
id: currentRow.value.id
};
console.log('📤 提交保存数据:', submitData);
// loading
loadingMessage = message.loading('保存图片中...', 0);
await funApi.save(submitData);
message.success('保存成功!');
//
uploadModalApi.close();
// gridApi.reload();
loadingMessage()
//
uploadFileList.value = [];
uploadedUrl.value = '';
@ -452,6 +357,9 @@ const [UploadModal, uploadModalApi] = useVbenModal({
} catch (error: any) {
console.error('❌ 保存失败:', error);
if (loadingMessage) {
loadingMessage();
}
message.error(error?.message || '保存失败');
}
} else {
@ -497,13 +405,7 @@ const getEditFormSchema = () => {
console.log('📦 新增表单内上传文件:', file);
try {
const formData = new FormData();
formData.append('file', file);
// API
const res = await funApi.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log(item.fieldName + ' 新增表单内上传成功,URL:', resultUrl);
message.success('上传成功!');
@ -545,6 +447,19 @@ const [Form, formApi] = useVbenForm({
},
})
// ========== ==========
async function uploadFile(file: File) {
let loadingMessage: any = null;
// loading
loadingMessage = message.loading('图片上传中...', 0);
const formData = new FormData();
formData.append('file', file);
const res = await funApi.upload(formData);
loadingMessage();
return res.result || res.message || res.url || res;
}
// ========== ==========
function openUploadDialog(fieldName: string, currentUrl: string) {
console.log('=== 打开上传对话框 ===', {
@ -559,7 +474,6 @@ function openUploadDialog(fieldName: string, currentUrl: string) {
uploadImageUrl.value = currentUrl || '';
uploadedUrl.value = ''; // URL
uploadFileList.value = []; //
uploadVisible.value = true;
uploadModalApi.open();
}
@ -575,17 +489,9 @@ async function handleCustomRequest(options: any) {
size: file.size,
lastModified: file.lastModified,
});
const formData = new FormData();
formData.append('file', file);
// API
const res = await funApi.upload(formData);
const resultUrl = res.result || res.message || res.url || res;
const resultUrl = await uploadFile(file);
console.log('✅ 上传成功,URL:', resultUrl);
message.success('上传成功!');
// URL
uploadedUrl.value = resultUrl;
console.log('=== uploadedUrl 赋值后 ===', uploadedUrl.value);
@ -608,20 +514,6 @@ async function handleCustomRequest(options: any) {
}
}
// ==========
function handleChange(info: any) {
const {status} = info.file;
console.log('📋 文件状态变化:', status, info.file);
if (status === 'done') {
console.log('✅ 上传完成响应:', info);
} else if (status === 'error') {
console.error('❌ 上传失败:', info);
message.error(`${info.file.name} 上传失败`);
}
}
// ========== ==========
function handleAdd() {
isEdit.value = false;
@ -679,7 +571,6 @@ function handleReset() {
queryFormApi.resetForm();
gridApi.reload();
}
</script>
@ -728,7 +619,6 @@ function handleReset() {
<Form/>
</Modal>
<!-- 上传对话框 -->
<!-- 上传对话框 -->
<UploadModal>
<div style="padding: 20px;margin-top: 16px; text-align: center;">
<Upload
@ -769,7 +659,7 @@ function handleReset() {
<div v-if="uploadImageUrl && !uploadedUrl" style="margin-top: 16px; text-align: center;">
<p style="color: #999; font-size: 12px; margin-bottom: 8px;">当前图片:</p>
<Image
:src="uploadImageUrl.startsWith('http') || uploadImageUrl.startsWith('/') ? uploadImageUrl : `${API_BASE_URL}${uploadImageUrl}`"
:src="getFullUrl(uploadImageUrl)"
style="max-width: 200px; border-radius: 4px;"
:preview="true"
/>

Loading…
Cancel
Save