diff --git a/packages/app/src/components/form.fields/upload/index.tsx b/packages/app/src/components/form.fields/upload/index.tsx
index e4e55dd81..5f7042933 100644
--- a/packages/app/src/components/form.fields/upload/index.tsx
+++ b/packages/app/src/components/form.fields/upload/index.tsx
@@ -9,6 +9,9 @@ import {
   InboxOutlined
 } from '@ant-design/icons'
 const { Dragger: UploadDragger } = AntdUpload
+import get from 'lodash/get';
+import findIndex from 'lodash/findIndex';
+import Lightbox from 'react-image-lightbox';
 
 const exts = [
   {
@@ -171,10 +174,19 @@ function toValues(fileList) {
   return fileList.map(toValue);
 }
 
+export function getImgUrls(value) {
+  const values = Array.isArray(value) ? value : [value];
+  return values.filter(item => testUrl(item.url, {
+    exclude: ['.png', '.jpg', '.jpeg', '.gif']
+  })).map(item => toValue(item));
+}
+
 export const Upload = connect({
   getProps: mapStyledProps
 })((props) => {
   const { value, onChange } = props;
+  const [visible, setVisible] = useState(false);
+  const [imgIndex, setImgIndex] = useState(0);
   const [fileList, setFileList] = useState(toFileList(value));
   const uploadProps = {
     name: 'file',
@@ -185,15 +197,53 @@ export const Upload = connect({
       onChange(toValues(fileList));
     },
   };
+  const images = getImgUrls(fileList);
+  // console.log(images);
   return (
     
        {
+          const value = toValue(file)||{};
+          const index = findIndex(images, image => image.id === value.id);
+          if (index >= 0) {
+            setImgIndex(index);
+            setVisible(true);
+          } else {
+            window.location.href = value.url;
+          }
+        }}
+        // itemRender={(originNode, file, fileList) => {
+        //   console.log(file);
+        //   const value = toValue(file);
+        //   return (
+        //     
+        //       

+        //     
上传
       
+      {visible && 
 setVisible(false)}
+        onMovePrevRequest={() => {
+          setImgIndex((imgIndex + images.length - 1) % images.length);
+        }}
+        onMoveNextRequest={() => {
+          setImgIndex((imgIndex + 1) % images.length);
+        }}
+      />}
      
   )
 });
diff --git a/packages/app/src/components/views/Field/index.tsx b/packages/app/src/components/views/Field/index.tsx
index fe06a8495..a0a81dd7d 100644
--- a/packages/app/src/components/views/Field/index.tsx
+++ b/packages/app/src/components/views/Field/index.tsx
@@ -305,7 +305,7 @@ export function AttachmentFieldItem(props: any) {
           e.preventDefault();
         }
       }} className={'attachment-field-item'} target={'_blank'} href={url}>
-         +
+         {/*  .ant-upload {
+  flex-direction: column;
+}
+
+.attachment-field-item {
+  display: inline-block;
+  line-height: 0;
+  margin-right: 3px;
+  padding: 1px;
+  border: 1px solid #d9d9d9;
+  border-radius: 2px;
+  background: #fafafa;
+  img {
+    height: 18px;
+    border-radius: 2px;
+  }
 }
\ No newline at end of file
diff --git a/packages/plugin-pages/src/actions/getView.ts b/packages/plugin-pages/src/actions/getView.ts
index 0d78c3b28..2e2c1e593 100644
--- a/packages/plugin-pages/src/actions/getView.ts
+++ b/packages/plugin-pages/src/actions/getView.ts
@@ -52,7 +52,7 @@ const transforms = {
         prop.type = 'string'
       }
       if (field.get('component.tooltip')) {
-        prop.description = field.get('component.tooltip');
+        prop.description = `{{html('${field.get('component.tooltip')}')}}`;
       }
       if (field.get('name') === 'dataSource') {
         
@@ -182,7 +182,7 @@ export default async (ctx, next) => {
     const table = ctx.db.getTable(associatedName);
     const resourceField = table.getField(resourceFieldName);
     if (resourceField instanceof BELONGSTOMANY) {
-      console.log({associatedName, resourceField});
+      // console.log({associatedName, resourceField});
       throughName = resourceField.options.through;
     }
   }
@@ -239,7 +239,6 @@ export default async (ctx, next) => {
     });
     view.setDataValue('defaultTabName', get(defaultTabs, [0, 'name']));
   }
-
   if (view.get('type') === 'table') {
     view.setDataValue('rowViewName', 'form');
   }
       
       {/*  .ant-upload {
+  flex-direction: column;
+}
+
+.attachment-field-item {
+  display: inline-block;
+  line-height: 0;
+  margin-right: 3px;
+  padding: 1px;
+  border: 1px solid #d9d9d9;
+  border-radius: 2px;
+  background: #fafafa;
+  img {
+    height: 18px;
+    border-radius: 2px;
+  }
 }
\ No newline at end of file
diff --git a/packages/plugin-pages/src/actions/getView.ts b/packages/plugin-pages/src/actions/getView.ts
index 0d78c3b28..2e2c1e593 100644
--- a/packages/plugin-pages/src/actions/getView.ts
+++ b/packages/plugin-pages/src/actions/getView.ts
@@ -52,7 +52,7 @@ const transforms = {
         prop.type = 'string'
       }
       if (field.get('component.tooltip')) {
-        prop.description = field.get('component.tooltip');
+        prop.description = `{{html('${field.get('component.tooltip')}')}}`;
       }
       if (field.get('name') === 'dataSource') {
         
@@ -182,7 +182,7 @@ export default async (ctx, next) => {
     const table = ctx.db.getTable(associatedName);
     const resourceField = table.getField(resourceFieldName);
     if (resourceField instanceof BELONGSTOMANY) {
-      console.log({associatedName, resourceField});
+      // console.log({associatedName, resourceField});
       throughName = resourceField.options.through;
     }
   }
@@ -239,7 +239,6 @@ export default async (ctx, next) => {
     });
     view.setDataValue('defaultTabName', get(defaultTabs, [0, 'name']));
   }
-
   if (view.get('type') === 'table') {
     view.setDataValue('rowViewName', 'form');
   }