完善后台接口字段
This commit is contained in:
BIN
app/amazon/__pycache__/approve.cpython-312.pyc
Normal file
BIN
app/amazon/__pycache__/approve.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -229,6 +229,9 @@ public class ProductRiskTaskService {
|
|||||||
task.setSuccessFileCount(ok);
|
task.setSuccessFileCount(ok);
|
||||||
task.setFailedFileCount(fail);
|
task.setFailedFileCount(fail);
|
||||||
task.setUpdatedAt(LocalDateTime.now());
|
task.setUpdatedAt(LocalDateTime.now());
|
||||||
|
|
||||||
|
log.info("[product-risk] reconcile summary taskId={} ok={} fail={} allDone={}",
|
||||||
|
taskId, ok, fail, allDone);
|
||||||
if (!allDone) {
|
if (!allDone) {
|
||||||
task.setStatus("RUNNING");
|
task.setStatus("RUNNING");
|
||||||
task.setErrorMessage(null);
|
task.setErrorMessage(null);
|
||||||
@@ -399,10 +402,17 @@ public class ProductRiskTaskService {
|
|||||||
payloadByShop.put(key, p);
|
payloadByShop.put(key, p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.info("[product-risk] submitResult received taskId={} payloadShopCount={} payloadKeys={}",
|
||||||
|
taskId, payloadByShop.size(), payloadByShop.keySet());
|
||||||
|
|
||||||
File workRoot = FileUtil.mkdir(FileUtil.file(System.getProperty("java.io.tmpdir"), "product-risk-result", String.valueOf(taskId)));
|
File workRoot = FileUtil.mkdir(FileUtil.file(System.getProperty("java.io.tmpdir"), "product-risk-result", String.valueOf(taskId)));
|
||||||
|
|
||||||
List<String> batchErrors = new ArrayList<>();
|
List<String> batchErrors = new ArrayList<>();
|
||||||
|
int matchedShopCount = 0;
|
||||||
|
int skippedUnmatchedCount = 0;
|
||||||
|
int waitingCount = 0;
|
||||||
|
int assembledCount = 0;
|
||||||
|
int fallbackMatchedCount = 0;
|
||||||
|
|
||||||
for (FileResultEntity fr : resultRows) {
|
for (FileResultEntity fr : resultRows) {
|
||||||
String shopKey = fr.getSourceFilename();
|
String shopKey = fr.getSourceFilename();
|
||||||
@@ -411,14 +421,17 @@ public class ProductRiskTaskService {
|
|||||||
// 兼容单店任务:若规范化店名偶发不一致(空格/符号差异)导致未命中,且任务与回传都只有 1 个店时按唯一店回填。
|
// 兼容单店任务:若规范化店名偶发不一致(空格/符号差异)导致未命中,且任务与回传都只有 1 个店时按唯一店回填。
|
||||||
if (payload == null && resultRows.size() == 1 && payloadByShop.size() == 1) {
|
if (payload == null && resultRows.size() == 1 && payloadByShop.size() == 1) {
|
||||||
payload = payloadByShop.values().iterator().next();
|
payload = payloadByShop.values().iterator().next();
|
||||||
|
fallbackMatchedCount++;
|
||||||
log.warn("[product-risk] single-shop fallback matched taskId={} dbShop={} payloadShop={}",
|
log.warn("[product-risk] single-shop fallback matched taskId={} dbShop={} payloadShop={}",
|
||||||
taskId, shopKey, payload.getShopName());
|
taskId, shopKey, payload.getShopName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload == null) {
|
if (payload == null) {
|
||||||
|
skippedUnmatchedCount++;
|
||||||
// 与删除品牌一致:支持队列逐条处理、分次回传,未在本次 payload 中的店铺保持待处理
|
// 与删除品牌一致:支持队列逐条处理、分次回传,未在本次 payload 中的店铺保持待处理
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
matchedShopCount++;
|
||||||
if (payload.getError() != null && !payload.getError().isBlank()) {
|
if (payload.getError() != null && !payload.getError().isBlank()) {
|
||||||
markResultFailed(fr, payload.getError());
|
markResultFailed(fr, payload.getError());
|
||||||
batchErrors.add(shopKey + ": " + payload.getError());
|
batchErrors.add(shopKey + ": " + payload.getError());
|
||||||
@@ -428,7 +441,16 @@ public class ProductRiskTaskService {
|
|||||||
|
|
||||||
// 分次上报累积:合并到 Redis 缓存,再按“合并后是否完成”决定是否出包。
|
// 分次上报累积:合并到 Redis 缓存,再按“合并后是否完成”决定是否出包。
|
||||||
ProductRiskShopPayloadDto mergedPayload = mergeShopPayload(taskId, shopKey, payload);
|
ProductRiskShopPayloadDto mergedPayload = mergeShopPayload(taskId, shopKey, payload);
|
||||||
if (!isShopPayloadCompleted(mergedPayload)) {
|
boolean shopDone = isShopPayloadCompleted(mergedPayload);
|
||||||
|
log.info("[product-risk] shop merged taskId={} shop={} incomingDone={} mergedDone={} mergedRows={} payloadCountries={}",
|
||||||
|
taskId,
|
||||||
|
shopKey,
|
||||||
|
payloadHasAnyDoneTrue(payload),
|
||||||
|
shopDone,
|
||||||
|
countPayloadRows(mergedPayload),
|
||||||
|
mergedPayload.getCountries() == null ? 0 : mergedPayload.getCountries().size());
|
||||||
|
if (!shopDone) {
|
||||||
|
waitingCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,6 +473,9 @@ public class ProductRiskTaskService {
|
|||||||
fr.setSuccess(1);
|
fr.setSuccess(1);
|
||||||
fr.setErrorMessage(null);
|
fr.setErrorMessage(null);
|
||||||
fileResultMapper.updateById(fr);
|
fileResultMapper.updateById(fr);
|
||||||
|
assembledCount++;
|
||||||
|
log.info("[product-risk] shop assembled taskId={} shop={} rowCount={} file={}",
|
||||||
|
taskId, shopKey, fr.getRowCount(), fr.getResultFilename());
|
||||||
FileUtil.del(xlsx);
|
FileUtil.del(xlsx);
|
||||||
FileUtil.del(zip);
|
FileUtil.del(zip);
|
||||||
productRiskTaskCacheService.removeShopMergedPayload(taskId, shopKey);
|
productRiskTaskCacheService.removeShopMergedPayload(taskId, shopKey);
|
||||||
@@ -708,6 +733,20 @@ public class ProductRiskTaskService {
|
|||||||
if (row == null) {
|
if (row == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 兼容 Python 末次“空行 done=true”心跳:视为当前国家已有行全部完成。
|
||||||
|
if (isDoneValue(row.getDone()) && isEmptyBusinessRow(row) && !byKey.isEmpty()) {
|
||||||
|
for (Map.Entry<String, ProductRiskRowDto> entry : byKey.entrySet()) {
|
||||||
|
ProductRiskRowDto existed = entry.getValue();
|
||||||
|
ProductRiskRowDto doneMerged = mergeRow(existed, row);
|
||||||
|
if (doneMerged.getDone() == null || doneMerged.getDone().isBlank()) {
|
||||||
|
doneMerged.setDone("true");
|
||||||
|
}
|
||||||
|
entry.setValue(doneMerged);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
String key = buildRowKey(row);
|
String key = buildRowKey(row);
|
||||||
ProductRiskRowDto prev = byKey.get(key);
|
ProductRiskRowDto prev = byKey.get(key);
|
||||||
byKey.put(key, mergeRow(prev, row));
|
byKey.put(key, mergeRow(prev, row));
|
||||||
@@ -760,6 +799,22 @@ public class ProductRiskTaskService {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isEmptyBusinessRow(ProductRiskRowDto row) {
|
||||||
|
if (row == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 注意:shopName 只是上下文信息,不作为业务行是否为空的判定条件。
|
||||||
|
// Python 末次心跳行通常只带 shopName + done=true,其他业务字段为空。
|
||||||
|
return isBlank(row.getProductAsinSku())
|
||||||
|
&& isBlank(row.getRemoveAsin())
|
||||||
|
&& isBlank(row.getStatus())
|
||||||
|
&& isBlank(row.getRemoveStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBlank(String val) {
|
||||||
|
return val == null || val.trim().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
private String firstNonBlank(String preferred, String fallback) {
|
private String firstNonBlank(String preferred, String fallback) {
|
||||||
if (preferred != null && !preferred.isBlank()) {
|
if (preferred != null && !preferred.isBlank()) {
|
||||||
return preferred;
|
return preferred;
|
||||||
@@ -771,22 +826,61 @@ public class ProductRiskTaskService {
|
|||||||
if (payload == null || payload.getCountries() == null || payload.getCountries().isEmpty()) {
|
if (payload == null || payload.getCountries() == null || payload.getCountries().isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean hasAnyRow = false;
|
boolean hasAnyBusinessRow = false;
|
||||||
for (List<ProductRiskRowDto> rows : payload.getCountries().values()) {
|
for (List<ProductRiskRowDto> rows : payload.getCountries().values()) {
|
||||||
if (rows == null || rows.isEmpty()) {
|
if (rows == null || rows.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (ProductRiskRowDto row : rows) {
|
for (ProductRiskRowDto row : rows) {
|
||||||
if (row == null) {
|
if (row == null || isEmptyBusinessRow(row)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
hasAnyRow = true;
|
hasAnyBusinessRow = true;
|
||||||
if (!isDoneValue(row.getDone())) {
|
if (!isDoneValue(row.getDone())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasAnyRow;
|
return hasAnyBusinessRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countPayloadRows(ProductRiskShopPayloadDto payload) {
|
||||||
|
if (payload == null || payload.getCountries() == null || payload.getCountries().isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int n = 0;
|
||||||
|
for (List<ProductRiskRowDto> rows : payload.getCountries().values()) {
|
||||||
|
if (rows == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (ProductRiskRowDto row : rows) {
|
||||||
|
if (row == null || isEmptyBusinessRow(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean payloadHasAnyDoneTrue(ProductRiskShopPayloadDto payload) {
|
||||||
|
if (payload == null || payload.getCountries() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (List<ProductRiskRowDto> rows : payload.getCountries().values()) {
|
||||||
|
if (rows == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (ProductRiskRowDto row : rows) {
|
||||||
|
if (row == null || isEmptyBusinessRow(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isDoneValue(row.getDone())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDoneValue(String value) {
|
private boolean isDoneValue(String value) {
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ public class ShopManageCreateRequest {
|
|||||||
@NotBlank(message = "店铺名不能为空")
|
@NotBlank(message = "店铺名不能为空")
|
||||||
private String shopName;
|
private String shopName;
|
||||||
|
|
||||||
|
@NotBlank(message = "店铺商城名不能为空")
|
||||||
|
private String mallName;
|
||||||
|
|
||||||
@NotBlank(message = "账号不能为空")
|
@NotBlank(message = "账号不能为空")
|
||||||
private String account;
|
private String account;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ public class ShopManageUpdateRequest {
|
|||||||
@NotBlank(message = "店铺名不能为空")
|
@NotBlank(message = "店铺名不能为空")
|
||||||
private String shopName;
|
private String shopName;
|
||||||
|
|
||||||
|
@NotBlank(message = "店铺商城名不能为空")
|
||||||
|
private String mallName;
|
||||||
|
|
||||||
@NotBlank(message = "账号不能为空")
|
@NotBlank(message = "账号不能为空")
|
||||||
private String account;
|
private String account;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.nanri.aiimage.modules.shopkey.model.entity;
|
package com.nanri.aiimage.modules.shopkey.model.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -16,6 +17,8 @@ public class ShopManageEntity {
|
|||||||
private Long groupId;
|
private Long groupId;
|
||||||
private String groupName;
|
private String groupName;
|
||||||
private String shopName;
|
private String shopName;
|
||||||
|
@TableField("mall_name")
|
||||||
|
private String mallName;
|
||||||
private String account;
|
private String account;
|
||||||
private String password;
|
private String password;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ public class ShopManageCredentialVo {
|
|||||||
private Long groupId;
|
private Long groupId;
|
||||||
private String groupName;
|
private String groupName;
|
||||||
private String shopName;
|
private String shopName;
|
||||||
|
private String mallName;
|
||||||
private String account;
|
private String account;
|
||||||
private String password;
|
private String password;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class ShopManageItemVo {
|
|||||||
private Long groupId;
|
private Long groupId;
|
||||||
private String groupName;
|
private String groupName;
|
||||||
private String shopName;
|
private String shopName;
|
||||||
|
private String mallName;
|
||||||
private String account;
|
private String account;
|
||||||
private String password;
|
private String password;
|
||||||
private String passwordMasked;
|
private String passwordMasked;
|
||||||
|
|||||||
@@ -57,12 +57,14 @@ Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
|
|||||||
public ShopManageItemVo create(ShopManageCreateRequest request) {
|
public ShopManageItemVo create(ShopManageCreateRequest request) {
|
||||||
ShopManageGroupEntity group = shopManageGroupService.getById(request.getGroupId());
|
ShopManageGroupEntity group = shopManageGroupService.getById(request.getGroupId());
|
||||||
String shopName = normalizeRequired(request.getShopName(), "店铺名不能为空");
|
String shopName = normalizeRequired(request.getShopName(), "店铺名不能为空");
|
||||||
|
String mallName = normalizeRequired(request.getMallName(), "店铺商城名不能为空");
|
||||||
ensureShopNameUnique(shopName, null);
|
ensureShopNameUnique(shopName, null);
|
||||||
|
|
||||||
ShopManageEntity entity = new ShopManageEntity();
|
ShopManageEntity entity = new ShopManageEntity();
|
||||||
entity.setGroupId(group.getId());
|
entity.setGroupId(group.getId());
|
||||||
entity.setGroupName(group.getGroupName());
|
entity.setGroupName(group.getGroupName());
|
||||||
entity.setShopName(shopName);
|
entity.setShopName(shopName);
|
||||||
|
entity.setMallName(mallName);
|
||||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||||
shopManageMapper.insert(entity);
|
shopManageMapper.insert(entity);
|
||||||
@@ -75,11 +77,13 @@ Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
|
|||||||
ShopManageEntity entity = getById(id);
|
ShopManageEntity entity = getById(id);
|
||||||
ShopManageGroupEntity group = shopManageGroupService.getById(request.getGroupId());
|
ShopManageGroupEntity group = shopManageGroupService.getById(request.getGroupId());
|
||||||
String shopName = normalizeRequired(request.getShopName(), "店铺名不能为空");
|
String shopName = normalizeRequired(request.getShopName(), "店铺名不能为空");
|
||||||
|
String mallName = normalizeRequired(request.getMallName(), "店铺商城名不能为空");
|
||||||
ensureShopNameUnique(shopName, id);
|
ensureShopNameUnique(shopName, id);
|
||||||
|
|
||||||
entity.setGroupId(group.getId());
|
entity.setGroupId(group.getId());
|
||||||
entity.setGroupName(group.getGroupName());
|
entity.setGroupName(group.getGroupName());
|
||||||
entity.setShopName(shopName);
|
entity.setShopName(shopName);
|
||||||
|
entity.setMallName(mallName);
|
||||||
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
entity.setAccount(normalizeRequired(request.getAccount(), "账号不能为空"));
|
||||||
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
entity.setPassword(shopCredentialCryptoService.encrypt(normalizeRequired(request.getPassword(), "密码不能为空")));
|
||||||
shopManageMapper.updateById(entity);
|
shopManageMapper.updateById(entity);
|
||||||
@@ -105,6 +109,7 @@ Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
|
|||||||
vo.setId(entity.getId());
|
vo.setId(entity.getId());
|
||||||
vo.setGroupId(entity.getGroupId());
|
vo.setGroupId(entity.getGroupId());
|
||||||
vo.setShopName(entity.getShopName());
|
vo.setShopName(entity.getShopName());
|
||||||
|
vo.setMallName(entity.getMallName());
|
||||||
vo.setAccount(entity.getAccount());
|
vo.setAccount(entity.getAccount());
|
||||||
vo.setPassword(shopCredentialCryptoService.decrypt(entity.getPassword()));
|
vo.setPassword(shopCredentialCryptoService.decrypt(entity.getPassword()));
|
||||||
try {
|
try {
|
||||||
@@ -166,6 +171,7 @@ Map<Long, String> groupNameById = buildGroupNameMap(rows.stream()
|
|||||||
vo.setGroupId(entity.getGroupId());
|
vo.setGroupId(entity.getGroupId());
|
||||||
vo.setGroupName(groupName == null ? "" : groupName);
|
vo.setGroupName(groupName == null ? "" : groupName);
|
||||||
vo.setShopName(entity.getShopName());
|
vo.setShopName(entity.getShopName());
|
||||||
|
vo.setMallName(entity.getMallName());
|
||||||
vo.setAccount(entity.getAccount());
|
vo.setAccount(entity.getAccount());
|
||||||
String masked = entity.getPassword() == null || entity.getPassword().isBlank() ? "" : "******";
|
String masked = entity.getPassword() == null || entity.getPassword().isBlank() ? "" : "******";
|
||||||
// 兼容旧前端字段:password 继续返回脱敏值
|
// 兼容旧前端字段:password 继续返回脱敏值
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
SET @db_name = DATABASE();
|
||||||
|
|
||||||
|
SET @mall_name_col_exists := (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM information_schema.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA = @db_name
|
||||||
|
AND TABLE_NAME = 'biz_shop_manage'
|
||||||
|
AND COLUMN_NAME = 'mall_name'
|
||||||
|
);
|
||||||
|
|
||||||
|
SET @sql_add_mall_name_col := IF(@mall_name_col_exists = 0,
|
||||||
|
'ALTER TABLE biz_shop_manage ADD COLUMN mall_name VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''店铺商城名'' AFTER shop_name',
|
||||||
|
'SELECT 1'
|
||||||
|
);
|
||||||
|
PREPARE stmt_add_mall_name_col FROM @sql_add_mall_name_col;
|
||||||
|
EXECUTE stmt_add_mall_name_col;
|
||||||
|
DEALLOCATE PREPARE stmt_add_mall_name_col;
|
||||||
Binary file not shown.
Binary file not shown.
@@ -961,6 +961,7 @@ def list_shop_manages():
|
|||||||
'group_id': item.get('groupId'),
|
'group_id': item.get('groupId'),
|
||||||
'group_name': item.get('groupName') or '',
|
'group_name': item.get('groupName') or '',
|
||||||
'shop_name': item.get('shopName') or '',
|
'shop_name': item.get('shopName') or '',
|
||||||
|
'mall_name': item.get('mallName') or '',
|
||||||
'account': item.get('account') or '',
|
'account': item.get('account') or '',
|
||||||
'password': item.get('passwordMasked') or '',
|
'password': item.get('passwordMasked') or '',
|
||||||
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
||||||
@@ -984,6 +985,7 @@ def create_shop_manage():
|
|||||||
payload = {
|
payload = {
|
||||||
'groupId': data.get('group_id'),
|
'groupId': data.get('group_id'),
|
||||||
'shopName': (data.get('shop_name') or '').strip(),
|
'shopName': (data.get('shop_name') or '').strip(),
|
||||||
|
'mallName': (data.get('mall_name') or '').strip(),
|
||||||
'account': (data.get('account') or '').strip(),
|
'account': (data.get('account') or '').strip(),
|
||||||
'password': (data.get('password') or '').strip(),
|
'password': (data.get('password') or '').strip(),
|
||||||
}
|
}
|
||||||
@@ -1003,6 +1005,7 @@ def create_shop_manage():
|
|||||||
'group_id': item.get('groupId'),
|
'group_id': item.get('groupId'),
|
||||||
'group_name': item.get('groupName') or '',
|
'group_name': item.get('groupName') or '',
|
||||||
'shop_name': item.get('shopName') or '',
|
'shop_name': item.get('shopName') or '',
|
||||||
|
'mall_name': item.get('mallName') or '',
|
||||||
'account': item.get('account') or '',
|
'account': item.get('account') or '',
|
||||||
'password': item.get('password') or '',
|
'password': item.get('password') or '',
|
||||||
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
||||||
@@ -1018,6 +1021,7 @@ def update_shop_manage(item_id):
|
|||||||
payload = {
|
payload = {
|
||||||
'groupId': data.get('group_id'),
|
'groupId': data.get('group_id'),
|
||||||
'shopName': (data.get('shop_name') or '').strip(),
|
'shopName': (data.get('shop_name') or '').strip(),
|
||||||
|
'mallName': (data.get('mall_name') or '').strip(),
|
||||||
'account': (data.get('account') or '').strip(),
|
'account': (data.get('account') or '').strip(),
|
||||||
'password': (data.get('password') or '').strip(),
|
'password': (data.get('password') or '').strip(),
|
||||||
}
|
}
|
||||||
@@ -1036,6 +1040,7 @@ def update_shop_manage(item_id):
|
|||||||
'id': item.get('id'),
|
'id': item.get('id'),
|
||||||
'group_name': item.get('groupName') or '',
|
'group_name': item.get('groupName') or '',
|
||||||
'shop_name': item.get('shopName') or '',
|
'shop_name': item.get('shopName') or '',
|
||||||
|
'mall_name': item.get('mallName') or '',
|
||||||
'account': item.get('account') or '',
|
'account': item.get('account') or '',
|
||||||
'password': item.get('password') or '',
|
'password': item.get('password') or '',
|
||||||
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
'created_at': (item.get('createdAt') or '').replace('T', ' ')[:16],
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ bucket_path = "nanri-image/"
|
|||||||
file_url_pre = f"https://{bucket}.oss-cn-hangzhou.aliyuncs.com/"
|
file_url_pre = f"https://{bucket}.oss-cn-hangzhou.aliyuncs.com/"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
# backend_java_base_url = os.environ.get('BACKEND_JAVA_BASE_URL', 'http://127.0.0.1:18080').rstrip('/')
|
backend_java_base_url = os.environ.get('BACKEND_JAVA_BASE_URL', 'http://127.0.0.1:18080').rstrip('/')
|
||||||
backend_java_base_url = os.environ.get('BACKEND_JAVA_BASE_URL', 'http://8.136.19.173:18080').rstrip('/')
|
# backend_java_base_url = os.environ.get('BACKEND_JAVA_BASE_URL', 'http://8.136.19.173:18080').rstrip('/')
|
||||||
os.environ['OSS_ACCESS_KEY_ID'] = accessKeyId
|
os.environ['OSS_ACCESS_KEY_ID'] = accessKeyId
|
||||||
os.environ['OSS_ACCESS_KEY_SECRET'] = accessKeySecret
|
os.environ['OSS_ACCESS_KEY_SECRET'] = accessKeySecret
|
||||||
os.environ['SECRET_KEY'] = "ddffc7c1d02121d9554d7b080b2511b6"
|
os.environ['SECRET_KEY'] = "ddffc7c1d02121d9554d7b080b2511b6"
|
||||||
|
|||||||
@@ -364,6 +364,10 @@
|
|||||||
<label>店铺名</label>
|
<label>店铺名</label>
|
||||||
<input type="text" id="shopManageShopName" placeholder="请输入店铺名称">
|
<input type="text" id="shopManageShopName" placeholder="请输入店铺名称">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" style="min-width:180px;">
|
||||||
|
<label>店铺商城名</label>
|
||||||
|
<input type="text" id="shopManageMallName" placeholder="请输入店铺商城名">
|
||||||
|
</div>
|
||||||
<div class="form-group" style="min-width:180px;">
|
<div class="form-group" style="min-width:180px;">
|
||||||
<label>账号</label>
|
<label>账号</label>
|
||||||
<input type="text" id="shopManageAccount" placeholder="请输入账号">
|
<input type="text" id="shopManageAccount" placeholder="请输入账号">
|
||||||
@@ -384,6 +388,7 @@
|
|||||||
<th>序号</th>
|
<th>序号</th>
|
||||||
<th>分组</th>
|
<th>分组</th>
|
||||||
<th>店铺名</th>
|
<th>店铺名</th>
|
||||||
|
<th>店铺商城名</th>
|
||||||
<th>账号</th>
|
<th>账号</th>
|
||||||
<th>密码</th>
|
<th>密码</th>
|
||||||
<th>创建时间</th>
|
<th>创建时间</th>
|
||||||
@@ -556,6 +561,10 @@
|
|||||||
<label>店铺名</label>
|
<label>店铺名</label>
|
||||||
<input type="text" id="editShopManageShopName" placeholder="店铺名">
|
<input type="text" id="editShopManageShopName" placeholder="店铺名">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>店铺商城名</label>
|
||||||
|
<input type="text" id="editShopManageMallName" placeholder="店铺商城名">
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>账号</label>
|
<label>账号</label>
|
||||||
<input type="text" id="editShopManageAccount" placeholder="账号">
|
<input type="text" id="editShopManageAccount" placeholder="账号">
|
||||||
@@ -1538,16 +1547,16 @@
|
|||||||
.then(function(res) {
|
.then(function(res) {
|
||||||
var tbody = document.getElementById('shopManageListBody');
|
var tbody = document.getElementById('shopManageListBody');
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
tbody.innerHTML = '<tr><td colspan="8" class="empty-tip">加载失败: ' + (res.error || '') + '</td></tr>';
|
tbody.innerHTML = '<tr><td colspan="9" class="empty-tip">加载失败: ' + (res.error || '') + '</td></tr>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var items = res.items || [];
|
var items = res.items || [];
|
||||||
if (items.length === 0) {
|
if (items.length === 0) {
|
||||||
tbody.innerHTML = '<tr><td colspan="8" class="empty-tip">暂无店铺</td></tr>';
|
tbody.innerHTML = '<tr><td colspan="9" class="empty-tip">暂无店铺</td></tr>';
|
||||||
} else {
|
} else {
|
||||||
tbody.innerHTML = items.map(function(item, index) {
|
tbody.innerHTML = items.map(function(item, index) {
|
||||||
var rowNo = (shopManagePage - 1) * shopManagePageSize + index + 1;
|
var rowNo = (shopManagePage - 1) * shopManagePageSize + index + 1;
|
||||||
return '<tr><td>' + rowNo + '</td><td>' + (item.group_name || '') + '</td><td>' + (item.shop_name || '') + '</td><td>' + (item.account || '') + '</td><td>' + (item.password || '') + '</td><td>' + (item.created_at || '') + '</td><td>' + (item.updated_at || '') + '</td><td>' +
|
return '<tr><td>' + rowNo + '</td><td>' + (item.group_name || '') + '</td><td>' + (item.shop_name || '') + '</td><td>' + (item.mall_name || '') + '</td><td>' + (item.account || '') + '</td><td>' + (item.password || '') + '</td><td>' + (item.created_at || '') + '</td><td>' + (item.updated_at || '') + '</td><td>' +
|
||||||
'<button class="btn btn-sm" data-shop-manage-edit="' + item.id + '" data-shop-manage="' + (JSON.stringify(item).replace(/"/g, '"')) + '">编辑</button> ' +
|
'<button class="btn btn-sm" data-shop-manage-edit="' + item.id + '" data-shop-manage="' + (JSON.stringify(item).replace(/"/g, '"')) + '">编辑</button> ' +
|
||||||
'<button class="btn btn-sm btn-danger" data-shop-manage-delete="' + item.id + '" data-shop-manage-name="' + (item.shop_name || '').replace(/"/g, '"') + '">删除</button>' +
|
'<button class="btn btn-sm btn-danger" data-shop-manage-delete="' + item.id + '" data-shop-manage-name="' + (item.shop_name || '').replace(/"/g, '"') + '">删除</button>' +
|
||||||
'</td></tr>';
|
'</td></tr>';
|
||||||
@@ -1557,7 +1566,7 @@
|
|||||||
bindShopManageActions();
|
bindShopManageActions();
|
||||||
})
|
})
|
||||||
.catch(function() {
|
.catch(function() {
|
||||||
document.getElementById('shopManageListBody').innerHTML = '<tr><td colspan="8" class="empty-tip">请求失败</td></tr>';
|
document.getElementById('shopManageListBody').innerHTML = '<tr><td colspan="9" class="empty-tip">请求失败</td></tr>';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1568,6 +1577,7 @@
|
|||||||
try { item = JSON.parse((btn.dataset.shopManage || '').replace(/"/g, '"')); } catch (e) { item = {}; }
|
try { item = JSON.parse((btn.dataset.shopManage || '').replace(/"/g, '"')); } catch (e) { item = {}; }
|
||||||
document.getElementById('editShopManageId').value = item.id || '';
|
document.getElementById('editShopManageId').value = item.id || '';
|
||||||
document.getElementById('editShopManageShopName').value = item.shop_name || '';
|
document.getElementById('editShopManageShopName').value = item.shop_name || '';
|
||||||
|
document.getElementById('editShopManageMallName').value = item.mall_name || '';
|
||||||
document.getElementById('editShopManageAccount').value = item.account || '';
|
document.getElementById('editShopManageAccount').value = item.account || '';
|
||||||
document.getElementById('editShopManagePassword').value = item.password || '';
|
document.getElementById('editShopManagePassword').value = item.password || '';
|
||||||
document.getElementById('msgEditShopManage').textContent = '';
|
document.getElementById('msgEditShopManage').textContent = '';
|
||||||
@@ -1643,26 +1653,28 @@
|
|||||||
document.getElementById('btnCreateShopManage').onclick = function() {
|
document.getElementById('btnCreateShopManage').onclick = function() {
|
||||||
var groupId = (document.getElementById('shopManageGroupSelect').value || '').trim();
|
var groupId = (document.getElementById('shopManageGroupSelect').value || '').trim();
|
||||||
var shopName = (document.getElementById('shopManageShopName').value || '').trim();
|
var shopName = (document.getElementById('shopManageShopName').value || '').trim();
|
||||||
|
var mallName = (document.getElementById('shopManageMallName').value || '').trim();
|
||||||
var account = (document.getElementById('shopManageAccount').value || '').trim();
|
var account = (document.getElementById('shopManageAccount').value || '').trim();
|
||||||
var password = (document.getElementById('shopManagePassword').value || '').trim();
|
var password = (document.getElementById('shopManagePassword').value || '').trim();
|
||||||
var msgEl = document.getElementById('msgShopManage');
|
var msgEl = document.getElementById('msgShopManage');
|
||||||
msgEl.textContent = '';
|
msgEl.textContent = '';
|
||||||
msgEl.className = 'msg';
|
msgEl.className = 'msg';
|
||||||
if (!groupId || !shopName || !account || !password) {
|
if (!groupId || !shopName || !mallName || !account || !password) {
|
||||||
msgEl.textContent = '请完整填写分组、店铺名、账号、密码';
|
msgEl.textContent = '请完整填写分组、店铺名、店铺商城名、账号、密码';
|
||||||
msgEl.classList.add('err');
|
msgEl.classList.add('err');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetch('/api/admin/shop-manage', {
|
fetch('/api/admin/shop-manage', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ group_id: Number(groupId), shop_name: shopName, account: account, password: password })
|
body: JSON.stringify({ group_id: Number(groupId), shop_name: shopName, mall_name: mallName, account: account, password: password })
|
||||||
})
|
})
|
||||||
.then(function(r) { return r.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(function(res) {
|
.then(function(res) {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
document.getElementById('shopManageGroupSelect').value = '';
|
document.getElementById('shopManageGroupSelect').value = '';
|
||||||
document.getElementById('shopManageShopName').value = '';
|
document.getElementById('shopManageShopName').value = '';
|
||||||
|
document.getElementById('shopManageMallName').value = '';
|
||||||
document.getElementById('shopManageAccount').value = '';
|
document.getElementById('shopManageAccount').value = '';
|
||||||
document.getElementById('shopManagePassword').value = '';
|
document.getElementById('shopManagePassword').value = '';
|
||||||
msgEl.textContent = res.msg || '创建成功';
|
msgEl.textContent = res.msg || '创建成功';
|
||||||
@@ -1683,20 +1695,21 @@
|
|||||||
var itemId = document.getElementById('editShopManageId').value;
|
var itemId = document.getElementById('editShopManageId').value;
|
||||||
var groupId = (document.getElementById('editShopManageGroupSelect').value || '').trim();
|
var groupId = (document.getElementById('editShopManageGroupSelect').value || '').trim();
|
||||||
var shopName = (document.getElementById('editShopManageShopName').value || '').trim();
|
var shopName = (document.getElementById('editShopManageShopName').value || '').trim();
|
||||||
|
var mallName = (document.getElementById('editShopManageMallName').value || '').trim();
|
||||||
var account = (document.getElementById('editShopManageAccount').value || '').trim();
|
var account = (document.getElementById('editShopManageAccount').value || '').trim();
|
||||||
var password = (document.getElementById('editShopManagePassword').value || '').trim();
|
var password = (document.getElementById('editShopManagePassword').value || '').trim();
|
||||||
var msgEl = document.getElementById('msgEditShopManage');
|
var msgEl = document.getElementById('msgEditShopManage');
|
||||||
msgEl.textContent = '';
|
msgEl.textContent = '';
|
||||||
msgEl.className = 'msg';
|
msgEl.className = 'msg';
|
||||||
if (!groupId || !shopName || !account || !password) {
|
if (!groupId || !shopName || !mallName || !account || !password) {
|
||||||
msgEl.textContent = '请完整填写分组、店铺名、账号、密码';
|
msgEl.textContent = '请完整填写分组、店铺名、店铺商城名、账号、密码';
|
||||||
msgEl.classList.add('err');
|
msgEl.classList.add('err');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetch('/api/admin/shop-manage/' + itemId, {
|
fetch('/api/admin/shop-manage/' + itemId, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ group_id: Number(groupId), shop_name: shopName, account: account, password: password })
|
body: JSON.stringify({ group_id: Number(groupId), shop_name: shopName, mall_name: mallName, account: account, password: password })
|
||||||
})
|
})
|
||||||
.then(function(r) { return r.json(); })
|
.then(function(r) { return r.json(); })
|
||||||
.then(function(res) {
|
.then(function(res) {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
<div class="country-pref-checks">
|
<div class="country-pref-checks">
|
||||||
<label v-for="row in countryCheckboxRows" :key="row.code" class="country-check-row">
|
<label v-for="row in countryCheckboxRows" :key="row.code" class="country-check-row">
|
||||||
<input type="checkbox" class="country-check-input" :checked="isCountrySelected(row.code)"
|
<input type="checkbox" class="country-check-input" :checked="isCountrySelected(row.code)"
|
||||||
|
:disabled="isCountrySelectionLocked(row.code)"
|
||||||
@change="onCountryNativeChange(row.code, $event)" />
|
@change="onCountryNativeChange(row.code, $event)" />
|
||||||
<span class="country-check-text">{{ row.label }}({{ row.code }})</span>
|
<span class="country-check-text">{{ row.label }}({{ row.code }})</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -278,9 +279,18 @@ function isCountrySelected(code: string) {
|
|||||||
return orderedCountryCodes.value.includes(code)
|
return orderedCountryCodes.value.includes(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isCountrySelectionLocked(code: string) {
|
||||||
|
return orderedCountryCodes.value.length === 1 && orderedCountryCodes.value[0] === code
|
||||||
|
}
|
||||||
|
|
||||||
function onCountryNativeChange(code: string, e: Event) {
|
function onCountryNativeChange(code: string, e: Event) {
|
||||||
const el = e.target as HTMLInputElement | null
|
const el = e.target as HTMLInputElement | null
|
||||||
if (!el) return
|
if (!el) return
|
||||||
|
if (!el.checked && isCountrySelectionLocked(code)) {
|
||||||
|
el.checked = true
|
||||||
|
ElMessage.warning('至少保留 1 个国家')
|
||||||
|
return
|
||||||
|
}
|
||||||
onCountryToggle(code, el.checked)
|
onCountryToggle(code, el.checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user