# 图片上传完整使用指南

# 📋 概述

本指南涵盖了项目中图片上传的完整功能,包括:

  • 图片上传组件 input_image_magnifier
  • 图片服务接口 image.php
  • 图片放大镜功能 image-magnifier.js
  • 完整的图片生命周期管理

# 🚀 快速开始

# 1. 基础图片上传组件

<!-- 最简单的用法 -->
<{input type="image_magnifier" name="image_field"}>

<!-- 完整参数示例 -->
<{input type="image_magnifier" 
        name="material_image" 
        target_type="material" 
        target_id="<{$material_info.bm_id}>" 
        display_width="150" 
        display_height="150" 
        magnifier="true"}>
1
2
3
4
5
6
7
8
9
10
11

# 2. 控制器中的图片处理

// 在控制器中处理图片上传
if (isset($_FILES['material_image']) && !empty($_FILES['material_image']['name'])) {
    $imageModel = app::get('image')->model('image');
    
    $result = $imageModel->uploadAndAttach(
        $_FILES['material_image']['tmp_name'],
        'material',
        $material_id,
        $_FILES['material_image']['name']
    );
    
    if (isset($result['error'])) {
        $this->end(false, '图片上传失败:' . $result['error']);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 🎯 核心组件

# input_image_magnifier 组件

# 参数说明

参数 类型 必需 默认值 说明
name string - 表单字段名称
image_src string - 图片源URL(最高优先级)
value string - 图片ID(第二优先级)
target_type string - 目标对象类型(第三优先级)
target_id string - 目标对象ID(第三优先级)
display_width int 50 显示宽度
display_height int 50 显示高度
magnifier bool true 是否启用放大镜

# 图片获取优先级

  1. 第一优先级image_src - 直接使用传入的图片URL
  2. 第二优先级value(image_id) - 通过 image.phpdump 方法获取
  3. 第三优先级target_type + target_id - 通过 getAttachedImages 方法获取

# 使用场景

<!-- 新增页面 -->
<{input type="image_magnifier" 
        name="material_image" 
        target_type="material" 
        display_width="150" 
        display_height="150"}>

<!-- 编辑页面 -->
<{input type="image_magnifier" 
        name="material_image" 
        target_type="material" 
        target_id="<{$material_info.bm_id}>" 
        display_width="150" 
        display_height="150"}>

<!-- 直接指定图片 -->
<{input type="image_magnifier" 
        name="material_image" 
        image_src="<{$image_url}>"}>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 🔧 图片服务接口

# 核心方法

# 1. uploadAndAttach() - 一站式上传

$imageModel = app::get('image')->model('image');

$result = $imageModel->uploadAndAttach(
    $file,           // 图片文件路径
    $target_type,    // 目标类型
    $target_id,      // 目标对象ID
    $name,           // 图片名称(可选)
    $sizes,          // 生成的尺寸数组(可选)
    $watermark       // 是否添加水印(可选)
);

// 返回:成功返回图片信息数组,失败返回 array('error' => '错误信息')
1
2
3
4
5
6
7
8
9
10
11
12

# 2. getAttachedImages() - 获取关联图片

$images = $imageModel->getAttachedImages(
    'material',      // 目标类型
    $material_id,    // 目标ID
    'S'              // 图片尺寸(可选:L/M/S)
);
1
2
3
4
5

# 3. detach() - 删除关联

$success = $imageModel->detach(
    $image_id,       // 图片ID
    'material',      // 目标类型
    $target_id,      // 目标ID
    true             // 是否同时删除文件
);
1
2
3
4
5
6

# 使用示例

# 物料图片管理

// 上传物料图片
if (isset($_FILES['material_image']) && !empty($_FILES['material_image']['name'])) {
    $imageModel = app::get('image')->model('image');
    
    $result = $imageModel->uploadAndAttach(
        $_FILES['material_image']['tmp_name'],
        'material',
        $material_id,
        $_FILES['material_image']['name']
    );
    
    if (isset($result['error'])) {
        $this->end(false, '图片上传失败:' . $result['error']);
    }
}

// 获取物料图片
$images = $imageModel->getAttachedImages('material', $material_id, 'M');
$mainImage = !empty($images) ? $images[0] : null;

// 删除物料图片
$imageModel->detach($image_id, 'material', $material_id, true);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 商品图片管理

// 上传商品图片(生成多尺寸)
$result = $imageModel->uploadAndAttach(
    $file,
    'goods',
    $goods_id,
    'product.jpg',
    ['L', 'M', 'S'],  // 生成大、中、小三种尺寸
    true               // 添加水印
);
1
2
3
4
5
6
7
8
9

# 🔍 图片放大镜功能

# 基本使用

图片放大镜功能已全局加载,无需额外引入。项目提供两种使用方式:

  1. 完整版 ImageMagnifier 类 - 功能强大,支持智能缩放、回调函数、动态配置
  2. 简化版全局函数 - 轻量级,可直接在HTML中使用

# HTML设置

<!-- 使用ref属性指定放大镜图片源(推荐) -->
<img src="thumb.jpg" ref="full-size.jpg" class="img-magnifier" />

<!-- 或者使用rel属性 -->
<img src="thumb.jpg" rel="full-size.jpg" class="img-magnifier" />

<!-- 使用data-src属性 -->
<img src="thumb.jpg" data-src="full-size.jpg" class="img-magnifier" />
1
2
3
4
5
6
7
8

# JavaScript调用

# 简化版全局函数(推荐用于简单场景)
// 为图片添加放大镜功能
showImageMagnifier(event, element);

// 更新放大镜位置
updateImageMagnifierPosition(event);

// 隐藏放大镜
hideImageMagnifier();
1
2
3
4
5
6
7
8
# 完整版 ImageMagnifier 类(推荐用于复杂场景)
// 单个元素
var magnifier = new ImageMagnifier('img.zoomable', {
    maxWidth: 800,
    maxHeight: 600,
    maxScale: 3
});

// 批量应用
var magnifiers = ImageMagnifier.applyToElements('.gallery img', {
    maxWidth: 600,
    maxHeight: 600
});

// 动态更新配置
magnifier.updateOptions({
    maxWidth: 800,
    maxHeight: 800
});

// 销毁实例
magnifier.destroy();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 配置选项

# 简化版配置

  • 最大尺寸:800x600px
  • 最大倍数:3倍放大
  • 智能缩放:自动计算最佳显示比例
  • 位置偏移:可调整显示位置

# 完整版配置

var options = {
    maxWidth: 800,           // 最大显示宽度
    maxHeight: 600,          // 最大显示高度
    maxScale: 3,             // 最大放大倍数
    offset: {x: 30, y: -20}, // 位置偏移
    className: 'magnifier-tip', // 自定义CSS类
    showDelay: 0,            // 显示延迟(ms)
    hideDelay: 0,            // 隐藏延迟(ms)
    fixed: false,            // 是否固定位置
    fade: true,              // 是否使用淡入淡出
    onShow: function(tip, element) {
        // 显示回调
        console.log('放大镜显示', element);
    },
    onHide: function(tip, element) {
        // 隐藏回调
        console.log('放大镜隐藏', element);
    },
    onLoad: function(img, size) {
        // 图片加载完成回调
        console.log('图片加载完成', size);
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 使用场景示例

# 产品图片展示

<div class="product-images">
    <img src="product-thumb-1.jpg" rel="product-full-1.jpg" class="product-img" />
    <img src="product-thumb-2.jpg" rel="product-full-2.jpg" class="product-img" />
</div>

<script>
// 为所有产品图片添加放大镜
ImageMagnifier.applyToElements('.product-img', {
    maxWidth: 500,
    maxHeight: 500,
    offset: {x: 20, y: -10}
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 图片上传预览

<div id="image-preview">
    <img id="uploaded-image" src="" style="display: none;" />
</div>

<script>
function previewImage(file) {
    var reader = new FileReader();
    reader.onload = function(e) {
        var img = $('uploaded-image');
        img.set('src', e.target.result);
        img.setStyle('display', 'block');
        
        // 添加放大镜
        new ImageMagnifier(img, {
            maxWidth: 600,
            maxHeight: 600
        });
    };
    reader.readAsDataURL(file);
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 📝 完整实现示例

# 1. 前端模板

<!-- app/material/view/admin/material/basic/edit.html -->
<{input type="image_magnifier" 
        name="material_image" 
        target_type="material" 
        target_id="<{$material_info.bm_id|default:''}>" 
        display_width="150" 
        display_height="150"}>
1
2
3
4
5
6
7

# 2. 后端控制器

// app/material/controller/admin/material/basic.php
public function toEdit() {
    // ... 其他逻辑 ...
    
    // 处理图片上传
    $submittedImageId = !empty($_POST['current_image_id']) ? $_POST['current_image_id'] : null;
    $originalImageId = null;
    
    if ($filter['bm_id']) {
        $imageModel = app::get('image')->model('image');
        $attachedImages = $imageModel->getAttachedImages('material', $filter['bm_id']);
        if ($attachedImages) {
            $originalImageId = $attachedImages[0]['image_id'];
        }
    }
    
    // 比较图片ID是否发生变化
    if ($submittedImageId !== $originalImageId) {
        // 删除原图片
        if ($originalImageId) {
            $imageModel->detach($originalImageId, 'material', $filter['bm_id'], true);
        }
        
        // 上传新图片
        if (isset($_FILES['material_image']) && !empty($_FILES['material_image']['name'])) {
            $result = $imageModel->uploadAndAttach(
                $_FILES['material_image']['tmp_name'],
                'material',
                $filter['bm_id'],
                $_FILES['material_image']['name']
            );
            
            if (isset($result['error'])) {
                $this->end(false, '图片上传失败:' . $result['error']);
            }
        }
    }
    
    // ... 其他逻辑 ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 3. 图片模型

// app/image/model/image.php
class image_mdl_image extends base_db_model {
    
    /**
     * 上传并关联图片
     */
    public function uploadAndAttach($file, $target_type, $target_id, $name = null, $sizes = null, $watermark = false) {
        // 验证文件
        if (!$this->validateUploadedFile($file)) {
            return array('error' => '文件验证失败');
        }
        
        // 处理图片
        $imageInfo = $this->processImage($file, $name, $sizes, $watermark);
        if (!$imageInfo) {
            return array('error' => '图片处理失败');
        }
        
        // 建立关联
        $attachId = $this->attach($imageInfo['image_id'], $target_type, $target_id);
        if (!$attachId) {
            return array('error' => '关联建立失败');
        }
        
        return $imageInfo;
    }
    
    /**
     * 验证上传文件
     */
    private function validateUploadedFile($file) {
        // 检查文件大小(最大2MB)
        if ($file['size'] > 2 * 1024 * 1024) {
            return false;
        }
        
        // 检查文件类型
        $allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
        if (!in_array($file['type'], $allowedTypes)) {
            return false;
        }
        
        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# ⚠️ 注意事项

# 1. 文件大小限制

  • 最大上传文件大小:2MB
  • 支持格式:JPEG、PNG、GIF

# 2. 错误处理

  • 所有图片操作都返回具体的错误信息
  • 控制器需要检查 error 键并返回给用户

# 3. 图片ID比较逻辑

  • 通过比较提交的 current_image_id 和数据库中的图片ID
  • 如果不一致,说明图片发生了变化,需要处理

# 4. 组件样式

  • 所有样式都统一在 input_image_magnifier.html 中管理
  • 使用该组件的页面无需重复定义样式

# 🔄 更新日志

# v2.0.0 (2024-12-XX)

  • ✅ 重构图片上传逻辑,使用ID比较方式
  • ✅ 简化前端删除标记机制
  • ✅ 统一图片验证和错误处理
  • ✅ 优化图片放大镜功能
  • ✅ 完善组件化设计

# v1.0.0 (2024-01-XX)

  • ✅ 初始版本发布
  • ✅ 基础图片上传功能
  • ✅ 图片放大镜组件
  • ✅ 图片服务接口

# 🏗️ 技术架构

# 文件结构

app/
├── desktop/
│   ├── statics/
│   │   ├── js/
│   │   │   └── image-magnifier.js          # 完整版放大镜组件
│   │   └── js_mini/
│   │       └── image-magnifier.js          # 压缩版放大镜组件
│   └── view/
│       └── input_image_magnifier.html      # 图片上传组件模板
├── image/
│   └── model/
│       └── image.php                        # 图片服务模型
└── material/
    ├── controller/
    │   └── admin/
    │       └── material/
    │           └── basic.php                # 物料控制器
    └── view/
        └── admin/
            └── material/
                └── basic/
                    ├── add.html             # 新增页面
                    └── edit.html            # 编辑页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 核心组件关系

  1. 前端组件input_image_magnifier 提供统一的图片上传界面
  2. 放大镜功能image-magnifier.js 提供图片预览放大功能
  3. 后端服务image.php 模型处理图片上传、存储、关联等逻辑
  4. 业务集成:各业务控制器调用图片服务,实现业务逻辑

# 数据流程

用户操作 → 前端组件 → 表单提交 → 控制器验证 → 图片服务处理 → 数据库存储 → 返回结果
1

# 🔧 故障排除

# 常见问题

# 1. 图片不显示

  • 检查图片路径是否正确
  • 确认 refreldata-src 属性设置正确
  • 查看浏览器控制台错误信息

# 2. 放大镜位置不正确

  • 调整 offset 配置
  • 检查页面CSS是否影响定位
  • 确认父容器的 position 设置

# 3. 图片上传失败

  • 检查文件大小是否超过2MB限制
  • 确认文件格式是否支持(JPEG、PNG、GIF)
  • 验证服务器权限和存储空间

# 4. 组件样式异常

  • 确认 input_image_magnifier.html 模板正确加载
  • 检查CSS冲突和覆盖问题
  • 验证MooTools依赖是否正确加载

# 调试技巧

// 在浏览器控制台中调试放大镜
console.log('ImageMagnifier:', typeof ImageMagnifier);

// 检查全局函数
console.log('showImageMagnifier:', typeof showImageMagnifier);

// 调试图片元素
var img = $('your-image-id');
console.log('Image element:', img);
console.log('Image attributes:', {
    src: img.get('src'),
    ref: img.get('ref'),
    rel: img.get('rel')
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14

最后更新:2024年12月
版本:v2.0.0
状态:✅ 可用于生产环境

最后更新: 11/11/2025, 9:12:34 PM