用户组新增二手交易上架数量限制与保底价格字段
- land_api.php 六处 web_user_groups 建表加 shop_max_listings/shop_min_price 列 - 三处 migrations 加 ALTER,handleUpdateUserGroup INSERT/bind 带两字段 - sync.php 建表/迁移/INSERT 同步两字段(配合Java推送) - admin.php 用户组新建/编辑表单与提交、列表详情显示两字段(-1=跟随全局)
This commit is contained in:
@@ -3026,6 +3026,8 @@ async function loadUserGroups(el) {
|
||||
html += `<span>💰 ${hasCustomPrice ? g.land_price_per_sqm+'债券/格²' : '默认'}</span>`;
|
||||
html += `<span>🏗️ ${hasCustomMax ? '最多'+g.max_lands+'块' : '默认'}</span>`;
|
||||
html += `<span>🔑 ${permCount}项默认权限</span>`;
|
||||
html += `<span>📦 二手上架: ${(g.shop_max_listings ?? -1) >= 0 ? '最多'+g.shop_max_listings+'件' : '跟随全局'}</span>`;
|
||||
html += `<span>🛡️ 保底价: ${(g.shop_min_price ?? -1) >= 0 ? g.shop_min_price+'债券' : '跟随全局'}</span>`;
|
||||
html += `</div>`;
|
||||
// 默认权限预览
|
||||
if (permCount > 0) {
|
||||
@@ -3120,6 +3122,16 @@ function showAddUserGroup() {
|
||||
<input id="ugMaxEffectLevel" type="number" value="256" min="1" max="256" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)">
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
|
||||
<div>
|
||||
<label style="display:block;font-size:12px;color:var(--dim);margin-bottom:4px">二手同时上架数上限(-1=跟随全局)</label>
|
||||
<input id="ugShopMaxListings" type="number" value="-1" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)">
|
||||
</div>
|
||||
<div>
|
||||
<label style="display:block;font-size:12px;color:var(--dim);margin-bottom:4px">二手保底价格(债券, -1=跟随全局)</label>
|
||||
<input id="ugShopMinPrice" type="number" value="-1" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)">
|
||||
</div>
|
||||
</div>
|
||||
<div style="font-size:11px;color:var(--dim);margin-bottom:10px">普通玩家按各效果的生存可获取上限封顶(如抗性提升最高 2 级、海豚的恩惠最高 1 级),严禁超限。填 256 表示不额外限制。</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
|
||||
<div>
|
||||
@@ -3166,6 +3178,8 @@ async function doAddUserGroup() {
|
||||
const renewPrice = document.getElementById('ugRenewPrice')?.value || '0';
|
||||
const duration = document.getElementById('ugDuration')?.value || '0';
|
||||
const autoRenew = document.getElementById('ugAutoRenew')?.checked ? '1' : '0';
|
||||
const shopMaxListings = document.getElementById('ugShopMaxListings')?.value || '-1';
|
||||
const shopMinPrice = document.getElementById('ugShopMinPrice')?.value || '-1';
|
||||
|
||||
if (!name || !/^[a-zA-Z0-9_]{2,20}$/.test(name)) {
|
||||
glassAlert('组ID仅允许英文字母、数字和下划线,2-20位');
|
||||
@@ -3178,6 +3192,7 @@ async function doAddUserGroup() {
|
||||
priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, max_effect_level: maxEffectLevel,
|
||||
home_limit: homeLimit, join_price: joinPrice, renew_price: renewPrice,
|
||||
duration_minutes: duration, auto_renew: autoRenew,
|
||||
shop_max_listings: shopMaxListings, shop_min_price: shopMinPrice,
|
||||
default_perms: '{}'
|
||||
}, 'POST');
|
||||
if (res.success) {
|
||||
@@ -3240,6 +3255,12 @@ async function showEditUserGroup(groupName) {
|
||||
<div><label style="display:block;font-size:12px;color:var(--dim);margin-bottom:4px">续费价格(债券)</label>
|
||||
<input id="eugRenewPrice" type="number" value="${g.renew_price || 0}" min="0" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)"></div>
|
||||
</div>`;
|
||||
html += `<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px">
|
||||
<div><label style="display:block;font-size:12px;color:var(--dim);margin-bottom:4px">二手同时上架数上限(-1=跟随全局)</label>
|
||||
<input id="eugShopMaxListings" type="number" value="${(g.shop_max_listings ?? -1)}" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)"></div>
|
||||
<div><label style="display:block;font-size:12px;color:var(--dim);margin-bottom:4px">二手保底价格(债券, -1=跟随全局)</label>
|
||||
<input id="eugShopMinPrice" type="number" value="${(g.shop_min_price ?? -1)}" style="width:100%;padding:8px;background:var(--bg);border:1px solid var(--border);border-radius:4px;color:var(--fg)"></div>
|
||||
</div>`;
|
||||
html += `<div style="margin-bottom:12px">
|
||||
<label style="display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dim);cursor:pointer">
|
||||
<input type="checkbox" id="eugAutoRenew" ${g.auto_renew == 1 ? 'checked' : ''} style="accent-color:#4caf50;width:14px;height:14px">
|
||||
@@ -3279,6 +3300,8 @@ async function doEditUserGroup(groupName) {
|
||||
const joinPrice = document.getElementById('eugJoinPrice')?.value || '0';
|
||||
const renewPrice = document.getElementById('eugRenewPrice')?.value || '0';
|
||||
const autoRenew = document.getElementById('eugAutoRenew')?.checked ? '1' : '0';
|
||||
const shopMaxListings = document.getElementById('eugShopMaxListings')?.value || '-1';
|
||||
const shopMinPrice = document.getElementById('eugShopMinPrice')?.value || '-1';
|
||||
|
||||
// 收集权限
|
||||
const perms = {};
|
||||
@@ -3292,6 +3315,7 @@ async function doEditUserGroup(groupName) {
|
||||
priority, land_price_per_sqm: price, max_lands: maxLands, max_effects: maxEffects, max_effect_level: maxEffectLevel,
|
||||
home_limit: homeLimit, duration_minutes: duration,
|
||||
join_price: joinPrice, renew_price: renewPrice, auto_renew: autoRenew,
|
||||
shop_max_listings: shopMaxListings, shop_min_price: shopMinPrice,
|
||||
default_perms: JSON.stringify(perms)
|
||||
}, 'POST');
|
||||
if (res.success) {
|
||||
|
||||
+24
-2
@@ -1709,6 +1709,8 @@ function getLandMaxEffects($db, $land) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2547,6 +2549,8 @@ function handleListUserGroups($db) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2569,6 +2573,8 @@ function handleListUserGroups($db) {
|
||||
'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0',
|
||||
'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5',
|
||||
'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256',
|
||||
'shop_max_listings' => 'ALTER TABLE web_user_groups ADD COLUMN shop_max_listings INTEGER DEFAULT -1',
|
||||
'shop_min_price' => 'ALTER TABLE web_user_groups ADD COLUMN shop_min_price INTEGER DEFAULT -1',
|
||||
];
|
||||
foreach ($migrations as $col => $sql) {
|
||||
if (!in_array($col, $columns)) {
|
||||
@@ -2608,6 +2614,8 @@ function handleUpdateUserGroup($db, $data) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2633,12 +2641,14 @@ function handleUpdateUserGroup($db, $data) {
|
||||
$durationMinutes = (int)($data['duration_minutes'] ?? 0);
|
||||
$autoRenew = (int)($data['auto_renew'] ?? 0);
|
||||
$defaultPerms = $data['default_perms'] ?? '{}';
|
||||
$shopMaxListings = (int)($data['shop_max_listings'] ?? -1);
|
||||
$shopMinPrice = (int)($data['shop_min_price'] ?? -1);
|
||||
|
||||
$stmt = $db->prepare("INSERT OR REPLACE INTO web_user_groups
|
||||
(group_name, display_name, display_color, display_emoji, priority,
|
||||
land_price_per_sqm, max_lands, max_effects, max_effect_level, home_limit, join_price, auto_renew, renew_price, duration_minutes, default_perms, synced_at)
|
||||
land_price_per_sqm, max_lands, max_effects, max_effect_level, home_limit, join_price, auto_renew, renew_price, duration_minutes, default_perms, shop_max_listings, shop_min_price, synced_at)
|
||||
VALUES (:name, :display, :color, :emoji, :priority,
|
||||
:price, :maxlands, :maxEffects, :maxEffectLevel, :homeLimit, :joinPrice, :autoRenew, :renewPrice, :duration, :perms, :synced)");
|
||||
:price, :maxlands, :maxEffects, :maxEffectLevel, :homeLimit, :joinPrice, :autoRenew, :renewPrice, :duration, :perms, :shopmax, :shopmin, :synced)");
|
||||
$stmt->bindValue(':name', $name, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':display', $displayName, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':color', $displayColor, SQLITE3_TEXT);
|
||||
@@ -2654,6 +2664,8 @@ function handleUpdateUserGroup($db, $data) {
|
||||
$stmt->bindValue(':renewPrice', $renewPrice, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':duration', $durationMinutes, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':perms', $defaultPerms, SQLITE3_TEXT);
|
||||
$stmt->bindValue(':shopmax', $shopMaxListings, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':shopmin', $shopMinPrice, SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':synced', time(), SQLITE3_INTEGER);
|
||||
$stmt->execute();
|
||||
|
||||
@@ -2837,6 +2849,8 @@ function handleGetPlayerGroups($db, $player) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2857,6 +2871,8 @@ function handleGetPlayerGroups($db, $player) {
|
||||
'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0',
|
||||
'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5',
|
||||
'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256',
|
||||
'shop_max_listings' => 'ALTER TABLE web_user_groups ADD COLUMN shop_max_listings INTEGER DEFAULT -1',
|
||||
'shop_min_price' => 'ALTER TABLE web_user_groups ADD COLUMN shop_min_price INTEGER DEFAULT -1',
|
||||
];
|
||||
foreach ($migrations as $col => $sql) {
|
||||
if (!in_array($col, $columns)) {
|
||||
@@ -2882,6 +2898,8 @@ function handleGetPlayerGroups($db, $player) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2919,6 +2937,8 @@ function handleListAvailableGroups($db) {
|
||||
max_lands INTEGER DEFAULT -1,
|
||||
max_effects INTEGER DEFAULT 5,
|
||||
max_effect_level INTEGER DEFAULT 256,
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
home_limit INTEGER DEFAULT 0,
|
||||
join_price INTEGER DEFAULT 0,
|
||||
auto_renew INTEGER DEFAULT 0,
|
||||
@@ -2937,6 +2957,8 @@ function handleListAvailableGroups($db) {
|
||||
'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0',
|
||||
'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5',
|
||||
'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256',
|
||||
'shop_max_listings' => 'ALTER TABLE web_user_groups ADD COLUMN shop_max_listings INTEGER DEFAULT -1',
|
||||
'shop_min_price' => 'ALTER TABLE web_user_groups ADD COLUMN shop_min_price INTEGER DEFAULT -1',
|
||||
];
|
||||
foreach ($migrations as $col => $sql) {
|
||||
if (!in_array($col, $columns)) {
|
||||
|
||||
+8
-2
@@ -969,6 +969,8 @@ function syncUserGroups() {
|
||||
renew_price INTEGER DEFAULT 0,
|
||||
duration_minutes INTEGER DEFAULT 0,
|
||||
default_perms TEXT DEFAULT '{}',
|
||||
shop_max_listings INTEGER DEFAULT -1,
|
||||
shop_min_price INTEGER DEFAULT -1,
|
||||
synced_at INTEGER DEFAULT 0
|
||||
)");
|
||||
|
||||
@@ -986,6 +988,8 @@ function syncUserGroups() {
|
||||
'duration_minutes' => 'ALTER TABLE web_user_groups ADD COLUMN duration_minutes INTEGER DEFAULT 0',
|
||||
'max_effects' => 'ALTER TABLE web_user_groups ADD COLUMN max_effects INTEGER DEFAULT 5',
|
||||
'max_effect_level' => 'ALTER TABLE web_user_groups ADD COLUMN max_effect_level INTEGER DEFAULT 256',
|
||||
'shop_max_listings' => 'ALTER TABLE web_user_groups ADD COLUMN shop_max_listings INTEGER DEFAULT -1',
|
||||
'shop_min_price' => 'ALTER TABLE web_user_groups ADD COLUMN shop_min_price INTEGER DEFAULT -1',
|
||||
];
|
||||
foreach ($migrations as $col => $sql) {
|
||||
if (!in_array($col, $columns)) {
|
||||
@@ -997,10 +1001,10 @@ function syncUserGroups() {
|
||||
$stmt = $db->prepare("INSERT OR REPLACE INTO web_user_groups
|
||||
(group_name, display_name, display_color, display_emoji, priority,
|
||||
land_price_per_sqm, max_lands, max_effects, max_effect_level, home_limit, join_price, auto_renew,
|
||||
renew_price, duration_minutes, default_perms, synced_at)
|
||||
renew_price, duration_minutes, default_perms, shop_max_listings, shop_min_price, synced_at)
|
||||
VALUES (:name, :display, :color, :emoji, :priority,
|
||||
:price, :maxlands, :maxeffects, :maxeffectlevel, :homelimit, :joinprice, :autorenew,
|
||||
:renewprice, :duration, :perms, :synced)");
|
||||
:renewprice, :duration, :perms, :shopmax, :shopmin, :synced)");
|
||||
$count = 0;
|
||||
foreach ($groups as $g) {
|
||||
$stmt->bindValue(':name', $g['group_name'] ?? '', SQLITE3_TEXT);
|
||||
@@ -1021,6 +1025,8 @@ function syncUserGroups() {
|
||||
$stmt->bindValue(':renewprice', (int)($g['renew_price'] ?? 0), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':duration', (int)($g['duration_minutes'] ?? 0), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':perms', $g['default_perms'] ?? '{}', SQLITE3_TEXT);
|
||||
$stmt->bindValue(':shopmax', (int)($g['shop_max_listings'] ?? -1), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':shopmin', (int)($g['shop_min_price'] ?? -1), SQLITE3_INTEGER);
|
||||
$stmt->bindValue(':synced', $now, SQLITE3_INTEGER);
|
||||
$stmt->execute();
|
||||
$count++;
|
||||
|
||||
Reference in New Issue
Block a user