<?php
/**
 * 炎酷CMS - 图片库选择组件
 * 用法：require 本文件后，在表单中调用 yk_image_field('字段name', '当前值', '标签')
 * JS 全局函数：ykMediaPick('输入框id') 打开弹窗，选中后回填输入框并更新 #id_preview 预览图
 * 对接接口（同事实现）：
 *   上传  POST /api/upload.php        表单字段 file，返回 {"code":0,"url":"uploads/..."}
 *   列表  GET  /api/upload.php?action=list&p=1
 */
defined('YKCMS') or exit('Access Denied');

/**
 * 图片选择字段小部件：label + 文本输入框 + 「上传/图库」按钮 + 预览图
 * @param string $name  输入框 name/id（id 必须合法，勿带 []）
 * @param string $value 当前图片路径（如 uploads/20260804/xxx.jpg）
 * @param string $label 表单标签
 * @param string $tip   附加提示（可空）
 */
function yk_image_field($name, $value, $label, $tip = '') {
    $value = (string)$value;
    echo '<div class="row"><label>' . e($label) . '</label><div class="ipt">';
    echo '<div style="display:flex;gap:8px;align-items:center">';
    echo '<input type="text" name="' . e($name) . '" id="' . e($name) . '" value="' . e($value) . '">';
    echo '<button type="button" class="yk-btn gray sm" style="white-space:nowrap" onclick="ykMediaPick(\'' . e($name) . '\')">上传/图库</button>';
    echo '</div>';
    echo '<div style="margin-top:8px"><img id="' . e($name) . '_preview" src="' . ($value !== '' ? e(yk_img_url($value)) : '') . '"'
        . ' style="max-width:160px;max-height:100px;border:1px solid #eaeef2;border-radius:4px;background:#f0f2f5;' . ($value !== '' ? '' : 'display:none') . '"></div>';
    if ($tip !== '') {
        echo '<div class="tip">' . e($tip) . '</div>';
    }
    echo '</div></div>';
    yk_medialib_assets();
}

/** 图片相对路径转可访问 URL */
function yk_img_url($path) {
    $path = (string)$path;
    if ($path === '') return '';
    if (preg_match('#^https?://#i', $path) || substr($path, 0, 1) === '/') return $path;
    return SITE_URL . '/' . ltrim($path, '/');
}

/**
 * 弹窗的 CSS/JS/HTML（每页只输出一次）
 */
function yk_medialib_assets() {
    static $done = false;
    if ($done) return;
    $done = true;
    $api = SITE_URL . '/api/upload.php';
    ?>
<style>
.yk-media-mask{display:none;position:fixed;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,.45);z-index:9999}
.yk-media-box{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:720px;max-width:94vw;max-height:86vh;background:#fff;border-radius:8px;display:flex;flex-direction:column;overflow:hidden}
.yk-media-head{display:flex;align-items:center;border-bottom:1px solid #eee}
.yk-media-head .tab{padding:12px 20px;cursor:pointer;font-size:14px;color:#666;border-bottom:2px solid transparent}
.yk-media-head .tab.on{color:#1e6fff;border-bottom-color:#1e6fff;font-weight:bold}
.yk-media-head .close{margin-left:auto;padding:0 18px;font-size:22px;cursor:pointer;color:#999;line-height:1}
.yk-media-head .close:hover{color:#333}
.yk-media-body{padding:16px;overflow-y:auto;flex:1}
.yk-media-grid{display:flex;flex-wrap:wrap;gap:10px}
.yk-media-grid .cell{width:calc(25% - 8px);border:2px solid #eaeef2;border-radius:6px;padding:6px;cursor:pointer;text-align:center;background:#fff;position:relative}
.yk-media-grid .cell:hover{border-color:#9ec0ff}
.yk-media-grid .cell.sel{border-color:#1e6fff}
.yk-media-grid .cell .del{position:absolute;top:-7px;right:-7px;width:20px;height:20px;line-height:18px;border-radius:50%;background:#d93025;color:#fff;font-size:13px;text-align:center;cursor:pointer;display:none}
.yk-media-grid .cell:hover .del{display:block}
.yk-media-grid .cell img{width:100%;height:80px;object-fit:cover;border-radius:4px;background:#f0f2f5}
.yk-media-grid .cell .nm{font-size:12px;color:#888;margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.yk-media-foot{padding:12px 16px;border-top:1px solid #eee;display:flex;align-items:center;justify-content:space-between}
.yk-media-pager a{display:inline-block;padding:4px 10px;border:1px solid #d5dae3;border-radius:3px;margin-right:5px;cursor:pointer;color:#333;font-size:13px}
.yk-media-pager a.on{background:#1e6fff;color:#fff;border-color:#1e6fff}
.yk-media-up{text-align:center;padding:40px 10px}
.yk-media-msg{color:#999;font-size:13px;text-align:center;padding:30px 0}
@media(max-width:768px){
 .yk-media-grid .cell{width:calc(50% - 5px)}
}
</style>
<div class="yk-media-mask" id="ykMediaMask">
  <div class="yk-media-box">
    <div class="yk-media-head">
      <div class="tab on" data-tab="lib" onclick="ykMediaTab('lib')">图片库</div>
      <div class="tab" data-tab="up" onclick="ykMediaTab('up')">本地上传</div>
      <div class="close" onclick="ykMediaClose()">&times;</div>
    </div>
    <div class="yk-media-body">
      <div id="ykMediaPaneLib">
        <div class="yk-media-grid" id="ykMediaGrid"></div>
        <div class="yk-media-msg" id="ykMediaMsg" style="display:none"></div>
      </div>
      <div id="ykMediaPaneUp" style="display:none">
        <div class="yk-media-up">
          <input type="file" id="ykMediaFile" accept="image/*">
          <div style="margin-top:14px"><button type="button" class="yk-btn" onclick="ykMediaUpload()">开始上传</button></div>
          <div class="tip" id="ykMediaUpTip" style="margin-top:10px;color:#999;font-size:12px">上传成功后自动选中该图片</div>
        </div>
      </div>
    </div>
    <div class="yk-media-foot">
      <div class="yk-media-pager" id="ykMediaPager"></div>
      <div><button type="button" class="yk-btn gray" onclick="ykMediaClose()">取消</button></div>
    </div>
  </div>
</div>
<script>
var YK_MEDIA_API = <?php echo json_encode($api); ?>;
var YK_SITE_URL  = <?php echo json_encode(SITE_URL); ?>;
var YK_CSRF      = <?php echo json_encode(function_exists('csrf_token') ? csrf_token() : ''); ?>;
var ykMediaTarget = null;
var ykMediaPage = 1;
var ykMediaSel = null;

function ykMediaPick(targetId, opts) {
    ykMediaTarget = targetId;
    ykMediaSel = null;
    ykMediaTab('lib');
    document.getElementById('ykMediaMask').style.display = 'block';
    ykMediaLoad(1);
}
function ykMediaClose() {
    document.getElementById('ykMediaMask').style.display = 'none';
}
function ykMediaTab(tab) {
    document.querySelectorAll('#ykMediaMask .tab').forEach(function (t) {
        t.className = 'tab' + (t.getAttribute('data-tab') === tab ? ' on' : '');
    });
    document.getElementById('ykMediaPaneLib').style.display = tab === 'lib' ? '' : 'none';
    document.getElementById('ykMediaPaneUp').style.display = tab === 'up' ? '' : 'none';
    if (tab === 'lib' && document.getElementById('ykMediaGrid').innerHTML === '') ykMediaLoad(ykMediaPage);
}
function ykMediaFull(url) {
    if (/^https?:\/\//i.test(url) || url.charAt(0) === '/') return url;
    return YK_SITE_URL + '/' + url;
}
function ykMediaLoad(p) {
    ykMediaPage = p;
    var grid = document.getElementById('ykMediaGrid');
    var msg = document.getElementById('ykMediaMsg');
    grid.innerHTML = '';
    msg.style.display = 'block';
    msg.textContent = '加载中…';
    fetch(YK_MEDIA_API + '?action=list&p=' + p, {credentials: 'same-origin'})
        .then(function (r) { return r.json(); })
        .then(function (res) {
            if (res.code !== 0) { msg.textContent = res.msg || '图片库加载失败'; return; }
            if (!res.list || !res.list.length) { msg.textContent = '图片库暂无图片，请切换到「本地上传」'; return; }
            msg.style.display = 'none';
            res.list.forEach(function (it) {
                var cell = document.createElement('div');
                cell.className = 'cell';
                cell.innerHTML = '<span class="del" title="删除图片（含文件）">&times;</span><img src="' + ykMediaFull(it.url) + '" alt=""><div class="nm">' + (it.name || it.url) + '</div>';
                cell.onclick = function () { ykMediaChoose(it.url); };
                cell.querySelector('.del').onclick = function (ev) {
                    ev.stopPropagation();
                    ykMediaDel(it.id);
                };
                grid.appendChild(cell);
            });
            var pager = document.getElementById('ykMediaPager');
            pager.innerHTML = '';
            for (var i = 1; i <= (res.pages || 1); i++) {
                (function (n) {
                    var a = document.createElement('a');
                    a.textContent = n;
                    if (n === p) a.className = 'on';
                    a.onclick = function () { ykMediaLoad(n); };
                    pager.appendChild(a);
                })(i);
            }
        })
        .catch(function () { msg.textContent = '图片库接口连接失败'; });
}
function ykMediaUpload() {
    var fi = document.getElementById('ykMediaFile');
    var tip = document.getElementById('ykMediaUpTip');
    if (!fi.files || !fi.files.length) { tip.textContent = '请先选择图片文件'; return; }
    var fd = new FormData();
    fd.append('file', fi.files[0]);
    fd.append('csrf_token', YK_CSRF);
    tip.textContent = '上传中…';
    fetch(YK_MEDIA_API, {method: 'POST', body: fd, credentials: 'same-origin'})
        .then(function (r) { return r.json(); })
        .then(function (res) {
            if (res.code === 0 && res.url) {
                tip.textContent = '上传成功';
                ykMediaChoose(res.url);
            } else {
                tip.textContent = '上传失败：' + (res.msg || '未知错误');
            }
        })
        .catch(function () { tip.textContent = '上传接口连接失败'; });
}
function ykMediaChoose(url) {
    var input = document.getElementById(ykMediaTarget);
    if (input) {
        input.value = url;
        var pv = document.getElementById(ykMediaTarget + '_preview');
        if (pv) { pv.src = ykMediaFull(url); pv.style.display = ''; }
    }
    ykMediaClose();
}
function ykMediaDel(id) {
    if (!confirm('确定删除该图片？将同时删除 uploads 中的文件。')) return;
    var fd = new FormData();
    fd.append('id', id);
    fd.append('csrf_token', YK_CSRF);
    fetch(YK_MEDIA_API + '?action=del', {method: 'POST', body: fd, credentials: 'same-origin'})
        .then(function (r) { return r.json(); })
        .then(function (res) {
            if (res.code === 0) { ykMediaLoad(ykMediaPage); }
            else { alert(res.msg || '删除失败'); }
        })
        .catch(function () { alert('删除接口连接失败'); });
}
</script>
    <?php
}
