v1.0.10
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据新增接口 POST /api/media/add.php
|
||||
* 必填:owner_type / owner_id / platform / account_id
|
||||
* 可选:profile_url / remark / is_primary + 商业属性(account_level/certification_type/follower_count 等)
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
require_once __DIR__ . '/../common/helpers.php';
|
||||
|
||||
checkAjax();
|
||||
checkPermission('media');
|
||||
|
||||
$data = extractFields(MEDIA_FIELDS);
|
||||
if (!in_array($data['owner_type'] ?? '', ['person', 'company'], true)) {
|
||||
Response::error('owner_type 必须为 person 或 company', 400);
|
||||
}
|
||||
if (empty($data['platform']) || empty($data['account_id'])) {
|
||||
Response::error('平台(platform)和账号(account_id)为必填项', 400);
|
||||
}
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
|
||||
// owner 存在性校验
|
||||
if ($data['owner_type'] === 'person') {
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM persons WHERE id = ?");
|
||||
} else {
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM companies WHERE id = ?");
|
||||
}
|
||||
$chk->execute([$data['owner_id']]);
|
||||
if ((int)$chk->fetchColumn() === 0) {
|
||||
Response::error('归属对象不存在', 400);
|
||||
}
|
||||
|
||||
// platform + account_id 唯一
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM social_accounts WHERE platform = ? AND account_id = ?");
|
||||
$chk->execute([$data['platform'], $data['account_id']]);
|
||||
if ((int)$chk->fetchColumn() > 0) {
|
||||
Response::error('该平台账号已存在', 400);
|
||||
}
|
||||
|
||||
[$sql, $params] = buildInsert($data);
|
||||
$pdo->prepare("INSERT INTO social_accounts $sql")->execute($params);
|
||||
$newId = (int)$pdo->lastInsertId();
|
||||
|
||||
// 写入商业属性
|
||||
$attr = extractFields(MEDIA_ATTR_FIELDS);
|
||||
if (!empty($attr)) {
|
||||
$attr['social_account_id'] = $newId;
|
||||
[$attrSql, $attrParams] = buildInsert($attr);
|
||||
$pdo->prepare("INSERT INTO media_commercial_attributes $attrSql")->execute($attrParams);
|
||||
}
|
||||
|
||||
logCurrent('add', 'media', 'social_accounts', $newId, ['data' => $data, 'attr' => $attr]);
|
||||
Response::success(['id' => $newId], '新增成功');
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据删除接口(软删除) POST /api/media/delete.php
|
||||
* 入参:id(或 ids 逗号分隔批量)
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
|
||||
checkAjax();
|
||||
checkPermission('media');
|
||||
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
$ids = trim($_POST['ids'] ?? '');
|
||||
$idList = [];
|
||||
if ($id > 0) $idList[] = $id;
|
||||
if ($ids !== '') {
|
||||
foreach (explode(',', $ids) as $v) {
|
||||
$v = (int)trim($v);
|
||||
if ($v > 0) $idList[] = $v;
|
||||
}
|
||||
}
|
||||
$idList = array_unique($idList);
|
||||
if (!$idList) {
|
||||
Response::error('参数错误', 400);
|
||||
}
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$in = implode(',', array_fill(0, count($idList), '?'));
|
||||
$stmt = $pdo->prepare("UPDATE social_accounts SET is_active = 0 WHERE id IN ($in)");
|
||||
$stmt->execute($idList);
|
||||
$affected = $stmt->rowCount();
|
||||
|
||||
logCurrent('delete', 'media', 'social_accounts', null, ['ids' => $idList]);
|
||||
Response::success(['affected' => $affected], "已删除 $affected 条记录");
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据详情接口 GET /api/media/detail.php?id=1
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
|
||||
checkPermission('media');
|
||||
|
||||
$id = (int)($_REQUEST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
Response::error('参数错误', 400);
|
||||
}
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT sa.*, mca.account_level, mca.content_categories, mca.follower_count,
|
||||
mca.avg_read_count, mca.certification_type, mca.special_requirements, mca.media_remark
|
||||
FROM social_accounts sa
|
||||
LEFT JOIN media_commercial_attributes mca ON mca.social_account_id = sa.id
|
||||
WHERE sa.id = ?"
|
||||
);
|
||||
$stmt->execute([$id]);
|
||||
$row = $stmt->fetch();
|
||||
if (!$row) {
|
||||
Response::error('媒体账号不存在');
|
||||
}
|
||||
|
||||
Response::success(['media' => $row]);
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据导出接口(CSV) GET/POST /api/media/export.php
|
||||
* 参数同 list.php
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
|
||||
checkPermission('media');
|
||||
|
||||
// 仅导出勾选的媒体账号
|
||||
$idsRaw = trim($_REQUEST['ids'] ?? '');
|
||||
$idList = [];
|
||||
if ($idsRaw !== '') {
|
||||
foreach (explode(',', $idsRaw) as $v) {
|
||||
$v = (int)trim($v);
|
||||
if ($v > 0) {
|
||||
$idList[] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
$idList = array_unique($idList);
|
||||
if (!$idList) {
|
||||
Response::error('请先选择需要导出的媒体数据', 1);
|
||||
}
|
||||
|
||||
$where = ['sa.id IN (' . implode(',', array_fill(0, count($idList), '?')) . ')', 'sa.is_active = 1'];
|
||||
$params = $idList;
|
||||
$whereSql = implode(' AND ', $where);
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT sa.id, sa.owner_type, sa.owner_id, sa.platform, sa.account_id, sa.profile_url, sa.remark,
|
||||
mca.account_level, mca.content_categories, mca.follower_count, mca.avg_read_count,
|
||||
mca.certification_type, sa.created_at,
|
||||
CASE sa.owner_type
|
||||
WHEN 'person' THEN (SELECT p.full_name FROM persons p WHERE p.id = sa.owner_id)
|
||||
WHEN 'company' THEN (SELECT c.display_name FROM companies c WHERE c.id = sa.owner_id)
|
||||
ELSE NULL END AS owner_name
|
||||
FROM social_accounts sa
|
||||
LEFT JOIN media_commercial_attributes mca ON mca.social_account_id = sa.id
|
||||
WHERE $whereSql ORDER BY sa.id DESC"
|
||||
);
|
||||
$stmt->execute($params);
|
||||
$list = $stmt->fetchAll();
|
||||
|
||||
logCurrent('export', 'media', 'social_accounts', null, ['count' => count($list)]);
|
||||
|
||||
header('Content-Type: text/csv; charset=utf-8');
|
||||
header('Content-Disposition: attachment; filename="media_' . date('Ymd_His') . '.csv"');
|
||||
echo "\xEF\xBB\xBF";
|
||||
$out = fopen('php://output', 'w');
|
||||
fputcsv($out, ['ID', '归属类型', '归属ID', '归属名称', '平台', '账号', '主页链接', '备注', '等级', '内容领域', '粉丝数', '平均阅读', '认证类型', '创建时间']);
|
||||
foreach ($list as $r) {
|
||||
fputcsv($out, [
|
||||
$r['id'], $r['owner_type'], $r['owner_id'], $r['owner_name'], $r['platform'],
|
||||
$r['account_id'], $r['profile_url'], $r['remark'], $r['account_level'],
|
||||
$r['content_categories'], $r['follower_count'], $r['avg_read_count'],
|
||||
$r['certification_type'], $r['created_at'],
|
||||
]);
|
||||
}
|
||||
fclose($out);
|
||||
exit;
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据 CSV 导入接口 POST /api/media/import.php (multipart/form-data, 字段名 file)
|
||||
* CSV 表头:owner_type,owner_id,platform,account_id,profile_url,remark,is_primary,
|
||||
* account_level,content_categories,follower_count,avg_read_count,certification_type
|
||||
* owner_type 为 person/company 时 owner_id 也可填对应名称(display_name/full_name),自动解析为ID。
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
|
||||
checkAjax();
|
||||
checkPermission('media');
|
||||
|
||||
if (empty($_FILES['file']) || $_FILES['file']['error'] !== UPLOAD_ERR_OK) {
|
||||
Response::error('请选择要上传的CSV文件', 400);
|
||||
}
|
||||
|
||||
$handle = fopen($_FILES['file']['tmp_name'], 'r');
|
||||
if (!$handle) {
|
||||
Response::error('无法读取文件', 400);
|
||||
}
|
||||
$first = preg_replace('/^\xEF\xBB\xBF/', '', fgets($handle));
|
||||
$header = str_getcsv(trim($first));
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$insAccount = $pdo->prepare(
|
||||
"INSERT INTO social_accounts (owner_type, owner_id, platform, account_id, profile_url, remark, is_primary, is_active)
|
||||
VALUES (?,?,?,?,?,?,?,1)"
|
||||
);
|
||||
$insAttr = $pdo->prepare(
|
||||
"INSERT INTO media_commercial_attributes
|
||||
(social_account_id, account_level, content_categories, follower_count, avg_read_count, certification_type)
|
||||
VALUES (?,?,?,?,?,?)"
|
||||
);
|
||||
|
||||
$inserted = 0;
|
||||
$failed = 0;
|
||||
|
||||
while (($row = fgetcsv($handle)) !== false) {
|
||||
$row = array_map('trim', $row);
|
||||
$rec = [];
|
||||
foreach ($header as $idx => $col) {
|
||||
$col = trim($col);
|
||||
if (isset($row[$idx])) {
|
||||
$rec[$col] = $row[$idx];
|
||||
}
|
||||
}
|
||||
if (empty($rec['platform']) || empty($rec['account_id']) || empty($rec['owner_type'])) {
|
||||
$failed++;
|
||||
continue;
|
||||
}
|
||||
$ownerType = $rec['owner_type'] === 'company' ? 'company' : 'person';
|
||||
$ownerId = (int)($rec['owner_id'] ?? 0);
|
||||
if ($ownerId <= 0) {
|
||||
// 按名称解析
|
||||
$nameCol = $ownerType === 'company' ? 'display_name' : 'full_name';
|
||||
$tbl = $ownerType === 'company' ? 'companies' : 'persons';
|
||||
$find = $pdo->prepare("SELECT id FROM $tbl WHERE $nameCol = ? LIMIT 1");
|
||||
$find->execute([$rec['owner_name'] ?? $rec['owner_id'] ?? '']);
|
||||
$ownerId = (int)$find->fetchColumn();
|
||||
}
|
||||
if ($ownerId <= 0) {
|
||||
$failed++;
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$chk = $pdo->prepare("SELECT COUNT(*) FROM social_accounts WHERE platform = ? AND account_id = ?");
|
||||
$chk->execute([$rec['platform'], $rec['account_id']]);
|
||||
if ((int)$chk->fetchColumn() > 0) {
|
||||
$failed++;
|
||||
continue;
|
||||
}
|
||||
$insAccount->execute([
|
||||
$ownerType, $ownerId, $rec['platform'], $rec['account_id'],
|
||||
$rec['profile_url'] ?? null, $rec['remark'] ?? null, !empty($rec['is_primary']) ? 1 : 0,
|
||||
]);
|
||||
$newId = (int)$pdo->lastInsertId();
|
||||
if (!empty($rec['account_level']) || !empty($rec['certification_type'])) {
|
||||
$insAttr->execute([
|
||||
$newId, $rec['account_level'] ?? null, $rec['content_categories'] ?? null,
|
||||
(int)($rec['follower_count'] ?? 0), (int)($rec['avg_read_count'] ?? 0),
|
||||
$rec['certification_type'] ?? null,
|
||||
]);
|
||||
}
|
||||
$inserted++;
|
||||
} catch (Exception $e) {
|
||||
$failed++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
|
||||
logCurrent('import', 'media', 'social_accounts', null, ['inserted' => $inserted, 'failed' => $failed]);
|
||||
Response::success(['inserted' => $inserted, 'failed' => $failed], "导入完成:成功 $inserted 条,失败 $failed 条");
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据列表接口 GET/POST /api/media/list.php
|
||||
* 参数:page / limit / keyword / platform / certification_type / account_level / owner_type / is_active
|
||||
* 数据源:social_accounts JOIN media_commercial_attributes
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
|
||||
checkPermission('media');
|
||||
|
||||
[$page, $limit] = pageParams();
|
||||
$keyword = trim($_REQUEST['keyword'] ?? '');
|
||||
$platform = trim($_REQUEST['platform'] ?? '');
|
||||
$certType = trim($_REQUEST['certification_type'] ?? '');
|
||||
$level = trim($_REQUEST['account_level'] ?? '');
|
||||
$ownerType = trim($_REQUEST['owner_type'] ?? '');
|
||||
$active = isset($_REQUEST['is_active']) && $_REQUEST['is_active'] !== '' ? (int)$_REQUEST['is_active'] : null;
|
||||
|
||||
$where = ['sa.is_active = 1'];
|
||||
$params = [];
|
||||
if ($active !== null) {
|
||||
$where = ['sa.is_active = ?'];
|
||||
$params = [$active];
|
||||
}
|
||||
if ($keyword !== '') {
|
||||
$where[] = "(sa.account_id LIKE ? OR sa.profile_url LIKE ? OR sa.owner_id IN (
|
||||
SELECT p.id FROM persons p WHERE p.full_name LIKE ?
|
||||
UNION SELECT c.id FROM companies c WHERE c.display_name LIKE ?
|
||||
))";
|
||||
$like = "%$keyword%";
|
||||
array_push($params, $like, $like, $like, $like);
|
||||
}
|
||||
if ($platform !== '') { $where[] = 'sa.platform = ?'; $params[] = $platform; }
|
||||
if ($certType !== '') { $where[] = 'mca.certification_type = ?'; $params[] = $certType; }
|
||||
if ($level !== '') { $where[] = 'mca.account_level = ?'; $params[] = $level; }
|
||||
if ($ownerType !== '') { $where[] = 'sa.owner_type = ?'; $params[] = $ownerType; }
|
||||
$whereSql = implode(' AND ', $where);
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT COUNT(*) FROM social_accounts sa
|
||||
LEFT JOIN media_commercial_attributes mca ON mca.social_account_id = sa.id
|
||||
WHERE $whereSql"
|
||||
);
|
||||
$stmt->execute($params);
|
||||
$total = (int)$stmt->fetchColumn();
|
||||
|
||||
$offset = ($page - 1) * $limit;
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT sa.id, sa.owner_type, sa.owner_id, sa.platform, sa.account_id, sa.profile_url,
|
||||
sa.remark, sa.is_primary, sa.is_active, sa.created_at,
|
||||
mca.account_level, mca.content_categories, mca.follower_count, mca.avg_read_count,
|
||||
mca.certification_type, mca.special_requirements, mca.media_remark,
|
||||
CASE sa.owner_type
|
||||
WHEN 'person' THEN (SELECT p.full_name FROM persons p WHERE p.id = sa.owner_id)
|
||||
WHEN 'company' THEN (SELECT c.display_name FROM companies c WHERE c.id = sa.owner_id)
|
||||
ELSE NULL END AS owner_name
|
||||
FROM social_accounts sa
|
||||
LEFT JOIN media_commercial_attributes mca ON mca.social_account_id = sa.id
|
||||
WHERE $whereSql
|
||||
ORDER BY sa.id DESC
|
||||
LIMIT $limit OFFSET $offset"
|
||||
);
|
||||
$stmt->execute($params);
|
||||
$list = $stmt->fetchAll();
|
||||
|
||||
// 供前端筛选下拉使用:平台/认证类型/等级 字典
|
||||
$dict = [
|
||||
'platforms' => $pdo->query("SELECT DISTINCT platform FROM social_accounts WHERE is_active = 1 ORDER BY platform")->fetchAll(PDO::FETCH_COLUMN),
|
||||
'certification_types' => $pdo->query("SELECT DISTINCT certification_type FROM media_commercial_attributes WHERE certification_type IS NOT NULL AND certification_type <> '' ORDER BY certification_type")->fetchAll(PDO::FETCH_COLUMN),
|
||||
'account_levels' => $pdo->query("SELECT DISTINCT account_level FROM media_commercial_attributes ORDER BY account_level")->fetchAll(PDO::FETCH_COLUMN),
|
||||
];
|
||||
|
||||
Response::success(['list' => $list, 'total' => $total, 'page' => $page, 'limit' => $limit, 'dict' => $dict]);
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* 媒体数据编辑接口 POST /api/media/update.php
|
||||
* 入参:id + 白名单字段(含商业属性)
|
||||
*/
|
||||
require_once __DIR__ . '/../common/db.php';
|
||||
require_once __DIR__ . '/../common/response.php';
|
||||
require_once __DIR__ . '/../common/auth.php';
|
||||
require_once __DIR__ . '/../common/logger.php';
|
||||
require_once __DIR__ . '/../common/helpers.php';
|
||||
|
||||
checkAjax();
|
||||
checkPermission('media');
|
||||
|
||||
$id = (int)($_POST['id'] ?? 0);
|
||||
if ($id <= 0) {
|
||||
Response::error('参数错误', 400);
|
||||
}
|
||||
|
||||
$pdo = DB::getInstance()->getPdo();
|
||||
$check = $pdo->prepare("SELECT * FROM social_accounts WHERE id = ?");
|
||||
$check->execute([$id]);
|
||||
$old = $check->fetch();
|
||||
if (!$old) {
|
||||
Response::error('媒体账号不存在');
|
||||
}
|
||||
|
||||
$data = extractFields(MEDIA_FIELDS);
|
||||
unset($data['owner_type'], $data['owner_id']); // 归属关系不允许改
|
||||
|
||||
if (!empty($data)) {
|
||||
[$sets, $params] = buildUpdate($data);
|
||||
$params[] = $id;
|
||||
$pdo->prepare("UPDATE social_accounts SET $sets WHERE id = ?")->execute($params);
|
||||
}
|
||||
|
||||
// 更新商业属性(存在则更新,不存在则插入)
|
||||
$attr = extractFields(MEDIA_ATTR_FIELDS);
|
||||
if (!empty($attr)) {
|
||||
$exists = $pdo->prepare("SELECT COUNT(*) FROM media_commercial_attributes WHERE social_account_id = ?");
|
||||
$exists->execute([$id]);
|
||||
if ((int)$exists->fetchColumn() > 0) {
|
||||
[$attrSets, $attrParams] = buildUpdate($attr);
|
||||
$attrParams[] = $id;
|
||||
$pdo->prepare("UPDATE media_commercial_attributes SET $attrSets WHERE social_account_id = ?")->execute($attrParams);
|
||||
} else {
|
||||
$attr['social_account_id'] = $id;
|
||||
[$attrSql, $attrParams] = buildInsert($attr);
|
||||
$pdo->prepare("INSERT INTO media_commercial_attributes $attrSql")->execute($attrParams);
|
||||
}
|
||||
}
|
||||
|
||||
logCurrent('update', 'media', 'social_accounts', $id, ['before' => $old, 'after' => $data, 'attr' => $attr]);
|
||||
Response::success(null, '更新成功');
|
||||
Reference in New Issue
Block a user