updata
This commit is contained in:
parent
d593b51ff9
commit
2ae4aa2d17
413
api/assets.js
413
api/assets.js
|
|
@ -395,6 +395,7 @@ function mapWalletFlowRecords(list, meta) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: buildRecordId(item, meta.key || "flow"),
|
id: buildRecordId(item, meta.key || "flow"),
|
||||||
|
sourceId: String(pickFirstValue(item, ["id", "log_id", "uid"]) || ""),
|
||||||
title: title,
|
title: title,
|
||||||
subtitle: orderSn ? "单号 " + orderSn : noteText || direction,
|
subtitle: orderSn ? "单号 " + orderSn : noteText || direction,
|
||||||
time: pickFirstValue(item, [
|
time: pickFirstValue(item, [
|
||||||
|
|
@ -420,6 +421,7 @@ function mapWalletFlowRecords(list, meta) {
|
||||||
directionLabel: direction,
|
directionLabel: direction,
|
||||||
actionSymbol: directionPresentation.actionSymbol,
|
actionSymbol: directionPresentation.actionSymbol,
|
||||||
orderSn: orderSn,
|
orderSn: orderSn,
|
||||||
|
noteText: noteText,
|
||||||
tag: directionPresentation.income ? "收" : "支",
|
tag: directionPresentation.income ? "收" : "支",
|
||||||
tone: directionPresentation.income ? "success" : "danger",
|
tone: directionPresentation.income ? "success" : "danger",
|
||||||
cardTone: directionPresentation.income ? "success" : "danger",
|
cardTone: directionPresentation.income ? "success" : "danger",
|
||||||
|
|
@ -631,30 +633,321 @@ function mapTransferRecords(list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapPointsConvertRecords(list) {
|
function mapPointsConvertRecords(list) {
|
||||||
return (Array.isArray(list) ? list : []).map(function (item) {
|
return normalizeListData(list).map(function (item) {
|
||||||
const numberText = toFixedNumber(item.number, 2);
|
const amountValue = pickFirstValue(item, [
|
||||||
const transferCoinText = toFixedNumber(item.transfer_coin_num, 0);
|
"number",
|
||||||
const releaseTotal =
|
"transfer_coin_num",
|
||||||
|
"point_num",
|
||||||
|
"num",
|
||||||
|
"amount",
|
||||||
|
"value",
|
||||||
|
]);
|
||||||
|
const rawStatusText = String(
|
||||||
|
pickFirstValue(item, [
|
||||||
|
"status_text",
|
||||||
|
"status_name",
|
||||||
|
"status_desc",
|
||||||
|
"transfer_status_text",
|
||||||
|
]) || "",
|
||||||
|
);
|
||||||
|
const rawStatusCode = String(
|
||||||
|
pickFirstValue(item, ["status", "state", "transfer_status"]) || "",
|
||||||
|
);
|
||||||
|
let statusText = rawStatusText;
|
||||||
|
let disabled = false;
|
||||||
|
|
||||||
|
if (!statusText) {
|
||||||
|
if (rawStatusCode === "1") {
|
||||||
|
statusText = "兑换中";
|
||||||
|
} else if (rawStatusCode === "2") {
|
||||||
|
statusText = "已转换";
|
||||||
|
} else if (rawStatusCode === "3") {
|
||||||
|
statusText = "转换失败";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
/中/.test(statusText) ||
|
||||||
|
/完成/.test(statusText) ||
|
||||||
|
/成功/.test(statusText) ||
|
||||||
|
/失败/.test(statusText)
|
||||||
|
) {
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: String(
|
||||||
|
pickFirstValue(item, ["id", "bill_id", "log_id", "sn"]) ||
|
||||||
|
Math.random(),
|
||||||
|
),
|
||||||
|
sourceId: String(pickFirstValue(item, ["id", "bill_id", "log_id"]) || ""),
|
||||||
|
orderSn: String(
|
||||||
|
pickFirstValue(item, ["order_sn", "trade_no", "bill_no", "sn"]) || "",
|
||||||
|
),
|
||||||
|
title:
|
||||||
|
pickFirstValue(item, ["title", "name", "type_name"]) ||
|
||||||
|
"系统赠送积分",
|
||||||
|
subtitle:
|
||||||
|
"可转数量 " +
|
||||||
|
formatTransferRecordNumber(
|
||||||
|
pickFirstValue(item, ["transfer_coin_num", "coin_num", "value"]) || 0,
|
||||||
|
),
|
||||||
|
time: pickFirstValue(item, [
|
||||||
|
"add_time",
|
||||||
|
"create_time",
|
||||||
|
"created_at",
|
||||||
|
"time",
|
||||||
|
"update_time",
|
||||||
|
]),
|
||||||
|
amount: "+" + formatLedgerRecordNumber(amountValue),
|
||||||
|
amountValue: toNumber(amountValue),
|
||||||
|
statusText: statusText,
|
||||||
|
disabled: disabled,
|
||||||
|
balance:
|
||||||
item &&
|
item &&
|
||||||
item.userBillRelease &&
|
item.userBillRelease &&
|
||||||
item.userBillRelease.total !== undefined &&
|
item.userBillRelease.total !== undefined &&
|
||||||
item.userBillRelease.total !== null
|
item.userBillRelease.total !== null
|
||||||
? String(item.userBillRelease.total)
|
? "释放总量 " + formatTransferRecordNumber(item.userBillRelease.total)
|
||||||
: "";
|
: "",
|
||||||
|
|
||||||
return {
|
|
||||||
id: String(item.id || ""),
|
|
||||||
title: item.title || "积分记录",
|
|
||||||
subtitle: "可转数量 " + transferCoinText,
|
|
||||||
time: item.add_time || "",
|
|
||||||
amount: "+" + numberText,
|
|
||||||
balance: releaseTotal ? "释放总量 " + releaseTotal : "",
|
|
||||||
tag: "积",
|
tag: "积",
|
||||||
tone: "success",
|
tone: disabled ? "warning" : "success",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function extractMonthLabel(value) {
|
||||||
|
const raw = String(value || "").trim();
|
||||||
|
|
||||||
|
if (!raw) {
|
||||||
|
const currentDate = new Date();
|
||||||
|
const year = currentDate.getFullYear();
|
||||||
|
const month = String(currentDate.getMonth() + 1).padStart(2, "0");
|
||||||
|
return year + "-" + month;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matcher = raw.match(/(\d{4})[-/.](\d{1,2})/);
|
||||||
|
if (matcher) {
|
||||||
|
return matcher[1] + "-" + String(matcher[2]).padStart(2, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new Date(raw.replace(/-/g, "/"));
|
||||||
|
if (Number.isNaN(date.getTime())) {
|
||||||
|
return raw.slice(0, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
date.getFullYear() +
|
||||||
|
"-" +
|
||||||
|
String(date.getMonth() + 1).padStart(2, "0")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPointsHistoryRecords(list) {
|
||||||
|
return mapWalletFlowRecords(list, {
|
||||||
|
key: "points-convert-history",
|
||||||
|
unit: "积分",
|
||||||
|
title: "积分记录",
|
||||||
|
subtitle: "可用积分流水",
|
||||||
|
}).map(function (item) {
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
month: extractMonthLabel(item.time),
|
||||||
|
detailAvailable: canOpenPointsConvertRecordDetail(item),
|
||||||
|
amountTone: item.actionSymbol === "+" ? "increase" : "decrease",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMonthOptions(list) {
|
||||||
|
const months = (Array.isArray(list) ? list : []).reduce(function (
|
||||||
|
result,
|
||||||
|
item,
|
||||||
|
) {
|
||||||
|
const month = item && item.month ? item.month : extractMonthLabel(item && item.time);
|
||||||
|
if (month && result.indexOf(month) === -1) {
|
||||||
|
result.push(month);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
months.sort(function (left, right) {
|
||||||
|
return right.localeCompare(left);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!months.length) {
|
||||||
|
months.push(extractMonthLabel(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
return months;
|
||||||
|
}
|
||||||
|
|
||||||
|
function canOpenPointsConvertRecordDetail(item) {
|
||||||
|
const target = item && typeof item === "object" ? item : {};
|
||||||
|
const contentText = [
|
||||||
|
target.title,
|
||||||
|
target.subtitle,
|
||||||
|
target.noteText,
|
||||||
|
target.feeText,
|
||||||
|
target.directionLabel,
|
||||||
|
]
|
||||||
|
.join(" ")
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
return (
|
||||||
|
Boolean(target.orderSn || target.sourceId) &&
|
||||||
|
/转换/.test(contentText) &&
|
||||||
|
!/bmt/.test(contentText)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractPointsConvertDetailItems(data) {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || typeof data !== "object") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data.list)) {
|
||||||
|
return data.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data.items)) {
|
||||||
|
return data.items;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data.details)) {
|
||||||
|
return data.details;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(data.records)) {
|
||||||
|
return data.records;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPointsConvertDetailFallback(record) {
|
||||||
|
const fallback = record || {};
|
||||||
|
const amountValue = String(fallback.amount || "").replace(/[^\d.-]/g, "");
|
||||||
|
|
||||||
|
return {
|
||||||
|
orderSn: fallback.orderSn || "",
|
||||||
|
totalAmount:
|
||||||
|
fallback.amount && String(fallback.amount).trim()
|
||||||
|
? String(fallback.amount)
|
||||||
|
: "+" + formatLedgerRecordNumber(amountValue),
|
||||||
|
time: fallback.time || "",
|
||||||
|
details: [
|
||||||
|
{
|
||||||
|
id: fallback.id || fallback.orderSn || "fallback-record",
|
||||||
|
title: fallback.title || "积分转换",
|
||||||
|
amount:
|
||||||
|
fallback.amount && String(fallback.amount).trim()
|
||||||
|
? String(fallback.amount)
|
||||||
|
: "+" + formatLedgerRecordNumber(amountValue),
|
||||||
|
time: fallback.time || "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildPointsConvertDetailPayload(data, fallbackRecord) {
|
||||||
|
const detailItems = extractPointsConvertDetailItems(data);
|
||||||
|
const summarySource =
|
||||||
|
data && typeof data === "object" && !Array.isArray(data) ? data : {};
|
||||||
|
const fallback = fallbackRecord || {};
|
||||||
|
const totalValue =
|
||||||
|
pickFirstValue(summarySource, [
|
||||||
|
"number",
|
||||||
|
"num",
|
||||||
|
"amount",
|
||||||
|
"point_num",
|
||||||
|
"transfer_coin_num",
|
||||||
|
"total",
|
||||||
|
]) || sumBy(detailItems, "number");
|
||||||
|
const totalAmountText =
|
||||||
|
totalValue !== ""
|
||||||
|
? "+" + formatLedgerRecordNumber(totalValue)
|
||||||
|
: fallback.amount || "+0";
|
||||||
|
const detailList = detailItems.map(function (item, index) {
|
||||||
|
const amountValue = pickFirstValue(item, [
|
||||||
|
"number",
|
||||||
|
"num",
|
||||||
|
"amount",
|
||||||
|
"point_num",
|
||||||
|
"transfer_coin_num",
|
||||||
|
"value",
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: String(
|
||||||
|
pickFirstValue(item, ["id", "bill_id", "log_id", "sn"]) ||
|
||||||
|
"detail-" + index,
|
||||||
|
),
|
||||||
|
title:
|
||||||
|
pickFirstValue(item, ["title", "name", "type_name"]) ||
|
||||||
|
fallback.title ||
|
||||||
|
"系统赠送积分",
|
||||||
|
amount: "+" + formatLedgerRecordNumber(amountValue),
|
||||||
|
time:
|
||||||
|
pickFirstValue(item, [
|
||||||
|
"add_time",
|
||||||
|
"create_time",
|
||||||
|
"created_at",
|
||||||
|
"time",
|
||||||
|
"update_time",
|
||||||
|
]) || fallback.time || "",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!detailList.length) {
|
||||||
|
return buildPointsConvertDetailFallback({
|
||||||
|
id: fallback.id,
|
||||||
|
orderSn:
|
||||||
|
String(
|
||||||
|
pickFirstValue(summarySource, [
|
||||||
|
"order_sn",
|
||||||
|
"trade_no",
|
||||||
|
"bill_no",
|
||||||
|
"sn",
|
||||||
|
]) || fallback.orderSn || "",
|
||||||
|
),
|
||||||
|
title:
|
||||||
|
pickFirstValue(summarySource, ["title", "name", "type_name"]) ||
|
||||||
|
fallback.title,
|
||||||
|
amount: totalAmountText,
|
||||||
|
time:
|
||||||
|
pickFirstValue(summarySource, [
|
||||||
|
"add_time",
|
||||||
|
"create_time",
|
||||||
|
"created_at",
|
||||||
|
"time",
|
||||||
|
"update_time",
|
||||||
|
]) || fallback.time,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
orderSn: String(
|
||||||
|
pickFirstValue(summarySource, ["order_sn", "trade_no", "bill_no", "sn"]) ||
|
||||||
|
fallback.orderSn ||
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
totalAmount: totalAmountText,
|
||||||
|
time:
|
||||||
|
pickFirstValue(summarySource, [
|
||||||
|
"add_time",
|
||||||
|
"create_time",
|
||||||
|
"created_at",
|
||||||
|
"time",
|
||||||
|
"update_time",
|
||||||
|
]) || fallback.time || "",
|
||||||
|
details: detailList,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildDefaultLedger(type, balances) {
|
function buildDefaultLedger(type, balances) {
|
||||||
const map = {
|
const map = {
|
||||||
power: {
|
power: {
|
||||||
|
|
@ -774,7 +1067,7 @@ async function fetchWalletAddressData(requestOptions) {
|
||||||
async function fetchPointsConvertList(requestOptions) {
|
async function fetchPointsConvertList(requestOptions) {
|
||||||
return fetchPayload(
|
return fetchPayload(
|
||||||
createRequestOptions({
|
createRequestOptions({
|
||||||
url: serviceConfig.ENDPOINTS.pointsConvertList,
|
url: serviceConfig.ENDPOINTS.pointsConvertAvailableList,
|
||||||
data: {
|
data: {
|
||||||
interval: serviceConfig.POINTS_CONVERT_INTERVAL,
|
interval: serviceConfig.POINTS_CONVERT_INTERVAL,
|
||||||
},
|
},
|
||||||
|
|
@ -783,6 +1076,18 @@ async function fetchPointsConvertList(requestOptions) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchPointsConvertHistoryListData(month, requestOptions) {
|
||||||
|
return fetchPayload(
|
||||||
|
createRequestOptions({
|
||||||
|
url: serviceConfig.ENDPOINTS.pointsConvertHistoryList,
|
||||||
|
data: {
|
||||||
|
month: month,
|
||||||
|
},
|
||||||
|
}, requestOptions),
|
||||||
|
"积分兑换列表加载失败",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchTransferLedgerData(requestOptions) {
|
async function fetchTransferLedgerData(requestOptions) {
|
||||||
return fetchPayload(
|
return fetchPayload(
|
||||||
createRequestOptions({
|
createRequestOptions({
|
||||||
|
|
@ -816,6 +1121,16 @@ async function fetchRedeemRecordListData(redeemType, requestOptions) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchPointsConvertInfoData(query, requestOptions) {
|
||||||
|
return fetchPayload(
|
||||||
|
createRequestOptions({
|
||||||
|
url: serviceConfig.ENDPOINTS.pointsConvertRecordDetail,
|
||||||
|
data: query || {},
|
||||||
|
}, requestOptions),
|
||||||
|
"积分转换详情加载失败",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchAssetHome(requestOptions) {
|
export async function fetchAssetHome(requestOptions) {
|
||||||
const result = await Promise.all([
|
const result = await Promise.all([
|
||||||
fetchPriceData(requestOptions),
|
fetchPriceData(requestOptions),
|
||||||
|
|
@ -824,31 +1139,65 @@ export async function fetchAssetHome(requestOptions) {
|
||||||
return buildHomeOverview(result[1], result[0]);
|
return buildHomeOverview(result[1], result[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPointsConvertDetail(requestOptions) {
|
export async function fetchPointsConvertHome(month, requestOptions) {
|
||||||
const result = await Promise.all([
|
const result = await Promise.all([
|
||||||
fetchHomeBalanceData(requestOptions),
|
fetchHomeBalanceData(requestOptions),
|
||||||
fetchPointsConvertList(requestOptions),
|
fetchPointsConvertHistoryListData(month, requestOptions),
|
||||||
]);
|
]);
|
||||||
const balances = normalizeBalances(result[0]);
|
const balances = normalizeBalances(result[0]);
|
||||||
const pointList = Array.isArray(result[1] && result[1].list)
|
const records = buildPointsHistoryRecords(result[1]).map(function (item) {
|
||||||
? result[1].list
|
return Object.assign({}, item, {
|
||||||
: [];
|
month: extractMonthLabel(item.time) || month,
|
||||||
|
detailAvailable: canOpenPointsConvertRecordDetail(item),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
availablePoints: toFixedNumber(balances.points, 2),
|
availablePoints: formatHomeNumber(balances.points, 0),
|
||||||
pendingPoints: toFixedNumber(sumBy(pointList, "number"), 0),
|
records: records,
|
||||||
ids: pointList
|
|
||||||
.map(function (item) {
|
|
||||||
return item && item.id;
|
|
||||||
})
|
|
||||||
.filter(Boolean),
|
|
||||||
tips: [
|
|
||||||
"释放中的积分,转换成可用积分后,方可兑换BMT;",
|
|
||||||
"凌晨0点-凌晨1点积分系统维护不可兑换。",
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchPointsConvertSelection(requestOptions) {
|
||||||
|
const data = await fetchPointsConvertList(requestOptions);
|
||||||
|
const items = mapPointsConvertRecords(data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: items,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchPointsConvertRecordDetail(record, requestOptions) {
|
||||||
|
const fallbackRecord = record || {};
|
||||||
|
const query = {};
|
||||||
|
|
||||||
|
if (fallbackRecord.sourceId) {
|
||||||
|
query.id = fallbackRecord.sourceId;
|
||||||
|
} else if (
|
||||||
|
fallbackRecord.id &&
|
||||||
|
fallbackRecord.orderSn &&
|
||||||
|
fallbackRecord.id !== fallbackRecord.orderSn
|
||||||
|
) {
|
||||||
|
query.id = fallbackRecord.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fallbackRecord.orderSn) {
|
||||||
|
query.order_sn = fallbackRecord.orderSn;
|
||||||
|
query.sn = fallbackRecord.orderSn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(query).length) {
|
||||||
|
return buildPointsConvertDetailFallback(fallbackRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await fetchPointsConvertInfoData(query, requestOptions);
|
||||||
|
return buildPointsConvertDetailPayload(data, fallbackRecord);
|
||||||
|
} catch (error) {
|
||||||
|
return buildPointsConvertDetailFallback(fallbackRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function submitAssetPointsConvert(payload, requestOptions) {
|
export async function submitAssetPointsConvert(payload, requestOptions) {
|
||||||
const ids = Array.isArray(payload && payload.ids) ? payload.ids : [];
|
const ids = Array.isArray(payload && payload.ids) ? payload.ids : [];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,10 @@ const serviceConfig = {
|
||||||
walletDetail: "/api/hn/wallet/getWalletAddress",
|
walletDetail: "/api/hn/wallet/getWalletAddress",
|
||||||
walletSave: "/api/hn/wallet/saveAddress",
|
walletSave: "/api/hn/wallet/saveAddress",
|
||||||
withdrawSubmit: "/api/hn/wallet/withdraw",
|
withdrawSubmit: "/api/hn/wallet/withdraw",
|
||||||
pointsConvertList: "/api/integral/transferList",
|
pointsConvertHistoryList: "/api/integral/getTransferList",
|
||||||
|
pointsConvertAvailableList: "/api/integral/transferList",
|
||||||
pointsConvertSubmit: "/api/integral/doTransfer",
|
pointsConvertSubmit: "/api/integral/doTransfer",
|
||||||
pointsConvertInfo: "/api/integral/transferInfo",
|
pointsConvertRecordDetail: "/api/integral/transferInfo",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,10 @@
|
||||||
"uniStatistics" : {
|
"uniStatistics" : {
|
||||||
"enable" : false
|
"enable" : false
|
||||||
},
|
},
|
||||||
"vueVersion" : "2"
|
"vueVersion" : "2",
|
||||||
|
"h5" : {
|
||||||
|
"router" : {
|
||||||
|
"base" : "/bmt/"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
pages.json
14
pages.json
|
|
@ -43,6 +43,20 @@
|
||||||
"backgroundColor": "#191E32"
|
"backgroundColor": "#191E32"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/assets/points-convert-list",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"backgroundColor": "#191E32"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/assets/points-convert-detail",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"backgroundColor": "#191E32"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/assets/ledger",
|
"path": "pages/assets/ledger",
|
||||||
"style": {
|
"style": {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,262 @@
|
||||||
|
<template>
|
||||||
|
<view class="asset-page asset-theme points-detail-page">
|
||||||
|
<asset-page-shell title="积分转换" />
|
||||||
|
|
||||||
|
<view class="asset-scroll points-detail-scroll">
|
||||||
|
<text class="detail-section-title">转换记录</text>
|
||||||
|
|
||||||
|
<view class="summary-card">
|
||||||
|
<view class="summary-card__top">
|
||||||
|
<text class="summary-card__order">
|
||||||
|
单号:
|
||||||
|
<text class="asset-number-font">{{ detail.orderSn || "--" }}</text>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<view class="summary-card__amount-box">
|
||||||
|
<text class="summary-card__amount-label">转换积分</text>
|
||||||
|
<text class="summary-card__amount asset-number-font">{{
|
||||||
|
detail.totalAmount
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class="summary-card__time asset-number-font">{{
|
||||||
|
detail.time || "--"
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="detail-card">
|
||||||
|
<text class="detail-card__title">转换明细</text>
|
||||||
|
|
||||||
|
<view
|
||||||
|
v-for="item in detail.details"
|
||||||
|
:key="item.id + '-' + item.time"
|
||||||
|
class="detail-item"
|
||||||
|
>
|
||||||
|
<view class="detail-item__main">
|
||||||
|
<text class="detail-item__title">{{ item.title }}</text>
|
||||||
|
<text class="detail-item__time asset-number-font">{{
|
||||||
|
item.time
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="detail-item__side">
|
||||||
|
<text class="detail-item__label">转换积分</text>
|
||||||
|
<text class="detail-item__amount asset-number-font">{{
|
||||||
|
item.amount
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AssetPageShell from "../../components/asset-page-shell.vue";
|
||||||
|
import { fetchPointsConvertRecordDetail } from "../../api/assets";
|
||||||
|
|
||||||
|
function parsePayload(value) {
|
||||||
|
if (!value) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return JSON.parse(decodeURIComponent(value));
|
||||||
|
} catch (error) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
AssetPageShell,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
recordPayload: {},
|
||||||
|
detail: {
|
||||||
|
orderSn: "",
|
||||||
|
totalAmount: "+0",
|
||||||
|
time: "",
|
||||||
|
details: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onLoad(options) {
|
||||||
|
this.recordPayload = parsePayload(options && options.payload);
|
||||||
|
this.loadPage(true);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async loadPage(showLoading) {
|
||||||
|
try {
|
||||||
|
this.detail = await fetchPointsConvertRecordDetail(
|
||||||
|
this.recordPayload,
|
||||||
|
showLoading
|
||||||
|
? {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "加载中",
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || "详情加载失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../styles/tokens.scss";
|
||||||
|
@import "../../styles/common.scss";
|
||||||
|
|
||||||
|
.points-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #191e32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.points-detail-scroll {
|
||||||
|
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
||||||
|
padding: 14rpx 14rpx calc(env(safe-area-inset-bottom) + 36rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-section-title {
|
||||||
|
display: block;
|
||||||
|
margin: 8rpx 2rpx 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card,
|
||||||
|
.detail-card {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background: #242944;
|
||||||
|
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -24rpx;
|
||||||
|
left: 42%;
|
||||||
|
width: 118rpx;
|
||||||
|
height: 210rpx;
|
||||||
|
background: rgba(123, 137, 190, 0.18);
|
||||||
|
transform: rotate(30deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__top {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx 26rpx;
|
||||||
|
border-bottom: 1px solid rgba(129, 141, 183, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__order {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__amount-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-left: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__amount-label {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: rgba(242, 245, 255, 0.94);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__amount {
|
||||||
|
margin-left: 8rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff8d62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__time {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: block;
|
||||||
|
padding: 20rpx 26rpx 22rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: rgba(228, 233, 250, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card {
|
||||||
|
margin-top: 2rpx;
|
||||||
|
padding: 28rpx 26rpx 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-card__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx 0;
|
||||||
|
border-top: 1px solid rgba(129, 141, 183, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item:first-of-type {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__time {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: rgba(158, 170, 204, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__side {
|
||||||
|
margin-left: 18rpx;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__label {
|
||||||
|
display: block;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: rgba(240, 243, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-item__amount {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff8d62;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,658 @@
|
||||||
|
<template>
|
||||||
|
<view class="asset-page asset-theme points-list-page">
|
||||||
|
<asset-page-shell title="积分转换" />
|
||||||
|
|
||||||
|
<view class="asset-scroll points-list-scroll">
|
||||||
|
<view class="summary-card">
|
||||||
|
<text class="summary-card__text">
|
||||||
|
已选择订单:
|
||||||
|
<text class="summary-card__accent asset-number-font">{{
|
||||||
|
selectedCount
|
||||||
|
}}</text>
|
||||||
|
个;共
|
||||||
|
<text class="summary-card__accent asset-number-font">{{
|
||||||
|
displaySelectedTotal
|
||||||
|
}}</text>
|
||||||
|
积分
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="selection-card">
|
||||||
|
<text class="selection-card__title">按订单积分区间筛选</text>
|
||||||
|
|
||||||
|
<view class="range-tabs">
|
||||||
|
<view
|
||||||
|
v-for="tab in rangeTabs"
|
||||||
|
:key="tab.key"
|
||||||
|
class="range-tabs__item"
|
||||||
|
:class="{ 'range-tabs__item--active': activeRange === tab.key }"
|
||||||
|
@click="activeRange = tab.key"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="filteredItems.length" class="selection-list">
|
||||||
|
<view
|
||||||
|
v-for="item in filteredItems"
|
||||||
|
:key="item.id"
|
||||||
|
class="selection-item"
|
||||||
|
:class="{ 'selection-item--disabled': item.disabled }"
|
||||||
|
@click="toggleItem(item)"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="selection-item__checkbox"
|
||||||
|
:class="{
|
||||||
|
'selection-item__checkbox--checked': isChecked(item),
|
||||||
|
'selection-item__checkbox--disabled': item.disabled,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<text
|
||||||
|
v-if="isChecked(item)"
|
||||||
|
class="selection-item__checkbox-mark"
|
||||||
|
>✓</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="selection-item__main">
|
||||||
|
<view class="selection-item__title-row">
|
||||||
|
<text class="selection-item__title">{{ item.title }}</text>
|
||||||
|
<view
|
||||||
|
v-if="item.statusText"
|
||||||
|
class="selection-item__status"
|
||||||
|
:class="{
|
||||||
|
'selection-item__status--warning': item.disabled,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ item.statusText }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<text class="selection-item__time asset-number-font">{{
|
||||||
|
item.time
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="selection-item__side">
|
||||||
|
<text class="selection-item__label">转换积分</text>
|
||||||
|
<text class="selection-item__amount asset-number-font">{{
|
||||||
|
item.amount
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-else class="selection-empty">
|
||||||
|
<text class="selection-empty__title">暂无可转换订单</text>
|
||||||
|
<text class="selection-empty__desc">
|
||||||
|
当前筛选条件下没有符合条件的积分订单。
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="bottom-bar">
|
||||||
|
<view class="bottom-bar__check-all" @click="toggleAll">
|
||||||
|
<view
|
||||||
|
class="bottom-bar__checkbox"
|
||||||
|
:class="{ 'bottom-bar__checkbox--checked': allChecked }"
|
||||||
|
>
|
||||||
|
<text v-if="allChecked" class="bottom-bar__checkbox-mark">✓</text>
|
||||||
|
</view>
|
||||||
|
<text class="bottom-bar__check-all-text">全选</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
class="bottom-bar__button"
|
||||||
|
:class="{ 'bottom-bar__button--disabled': !canSubmit }"
|
||||||
|
@click="submit"
|
||||||
|
>
|
||||||
|
{{ submitting ? "提交中..." : "确认转换" }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import AssetPageShell from "../../components/asset-page-shell.vue";
|
||||||
|
import {
|
||||||
|
fetchPointsConvertSelection,
|
||||||
|
submitAssetPointsConvert,
|
||||||
|
} from "../../api/assets";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
AssetPageShell,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hasShown: false,
|
||||||
|
activeRange: "",
|
||||||
|
submitting: false,
|
||||||
|
selectedIds: [],
|
||||||
|
detail: {
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
rangeTabs() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: "below-20",
|
||||||
|
label: "20以下",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "20-100",
|
||||||
|
label: "20-100",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "100-200",
|
||||||
|
label: "100-200",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "200-500",
|
||||||
|
label: "200-500",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "500-plus",
|
||||||
|
label: "500以上",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
items() {
|
||||||
|
return Array.isArray(this.detail.items) ? this.detail.items : [];
|
||||||
|
},
|
||||||
|
filteredItems() {
|
||||||
|
return this.items.filter((item) => this.matchRange(item));
|
||||||
|
},
|
||||||
|
selectedItems() {
|
||||||
|
return this.items.filter(
|
||||||
|
(item) => !item.disabled && this.selectedIds.indexOf(item.id) > -1,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
selectedCount() {
|
||||||
|
return this.selectedItems.length;
|
||||||
|
},
|
||||||
|
selectedTotal() {
|
||||||
|
return this.selectedItems.reduce(
|
||||||
|
(total, item) => total + Number(item.amountValue || 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
displaySelectedTotal() {
|
||||||
|
return this.formatAmount(this.selectedTotal);
|
||||||
|
},
|
||||||
|
selectableFilteredItems() {
|
||||||
|
return this.filteredItems.filter((item) => !item.disabled);
|
||||||
|
},
|
||||||
|
allChecked() {
|
||||||
|
if (!this.selectableFilteredItems.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.selectableFilteredItems.every(
|
||||||
|
(item) => this.selectedIds.indexOf(item.id) > -1,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
canSubmit() {
|
||||||
|
return this.selectedItems.length > 0 && !this.submitting;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
this.loadPage(true);
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if (this.hasShown) {
|
||||||
|
this.loadPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasShown = true;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatAmount(value) {
|
||||||
|
const number = Number(value || 0);
|
||||||
|
if (!Number.isFinite(number)) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.round(number)
|
||||||
|
.toString()
|
||||||
|
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
|
},
|
||||||
|
matchRange(item) {
|
||||||
|
const amount = Number(item && item.amountValue ? item.amountValue : 0);
|
||||||
|
|
||||||
|
if (!this.activeRange) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activeRange === "below-20") {
|
||||||
|
return amount < 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activeRange === "20-100") {
|
||||||
|
return amount >= 20 && amount < 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activeRange === "100-200") {
|
||||||
|
return amount >= 100 && amount < 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activeRange === "200-500") {
|
||||||
|
return amount >= 200 && amount < 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.activeRange === "500-plus") {
|
||||||
|
return amount >= 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
resolveRangeByAmount(amount) {
|
||||||
|
const numericAmount = Number(amount || 0);
|
||||||
|
|
||||||
|
if (numericAmount < 20) {
|
||||||
|
return "below-20";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numericAmount < 100) {
|
||||||
|
return "20-100";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numericAmount < 200) {
|
||||||
|
return "100-200";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numericAmount < 500) {
|
||||||
|
return "200-500";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "500-plus";
|
||||||
|
},
|
||||||
|
isChecked(item) {
|
||||||
|
return this.selectedIds.indexOf(item.id) > -1;
|
||||||
|
},
|
||||||
|
toggleItem(item) {
|
||||||
|
if (!item || item.disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isChecked(item)) {
|
||||||
|
this.selectedIds = this.selectedIds.filter((id) => id !== item.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedIds = this.selectedIds.concat(item.id);
|
||||||
|
},
|
||||||
|
toggleAll() {
|
||||||
|
const currentIds = this.selectableFilteredItems.map((item) => item.id);
|
||||||
|
|
||||||
|
if (!currentIds.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.allChecked) {
|
||||||
|
this.selectedIds = this.selectedIds.filter(
|
||||||
|
(id) => currentIds.indexOf(id) === -1,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedIds = Array.from(new Set(this.selectedIds.concat(currentIds)));
|
||||||
|
},
|
||||||
|
async loadPage(showLoading) {
|
||||||
|
try {
|
||||||
|
const result = await fetchPointsConvertSelection(
|
||||||
|
showLoading
|
||||||
|
? {
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "加载中",
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.detail = result;
|
||||||
|
const validIds = this.items
|
||||||
|
.filter((item) => !item.disabled)
|
||||||
|
.map((item) => item.id);
|
||||||
|
this.selectedIds = this.selectedIds.filter(
|
||||||
|
(id) => validIds.indexOf(id) > -1,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rangeKeys = this.rangeTabs.map((item) => item.key);
|
||||||
|
if (rangeKeys.indexOf(this.activeRange) === -1) {
|
||||||
|
const firstItem = this.items[0];
|
||||||
|
this.activeRange = firstItem
|
||||||
|
? this.resolveRangeByAmount(firstItem.amountValue)
|
||||||
|
: this.rangeTabs[0].key;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || "页面加载失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
if (!this.canSubmit) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请选择可转换订单",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submitting = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await submitAssetPointsConvert(
|
||||||
|
{
|
||||||
|
ids: this.selectedItems.map((item) => item.sourceId || item.id),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
showLoading: true,
|
||||||
|
loadingText: "转换中",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: "转换成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack();
|
||||||
|
}, 400);
|
||||||
|
} catch (error) {
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || "转换失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
this.submitting = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../../styles/tokens.scss";
|
||||||
|
@import "../../styles/common.scss";
|
||||||
|
|
||||||
|
.points-list-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #191e32;
|
||||||
|
}
|
||||||
|
|
||||||
|
.points-list-scroll {
|
||||||
|
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
||||||
|
padding: 12rpx 14rpx calc(env(safe-area-inset-bottom) + 150rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card,
|
||||||
|
.selection-card,
|
||||||
|
.bottom-bar {
|
||||||
|
background: #242944;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card,
|
||||||
|
.selection-card,
|
||||||
|
.selection-empty {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 28rpx 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -18rpx;
|
||||||
|
left: 42%;
|
||||||
|
width: 110rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
background: rgba(123, 137, 190, 0.18);
|
||||||
|
transform: rotate(30deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__text {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-card__accent {
|
||||||
|
color: #ff8d62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-card {
|
||||||
|
margin-top: 18rpx;
|
||||||
|
padding: 28rpx 0 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-card__title {
|
||||||
|
display: block;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 26rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
border-bottom: 1px solid rgba(129, 141, 183, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs__item {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 4rpx 18rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: rgba(173, 182, 211, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs__item--active {
|
||||||
|
color: #ff8d62;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.range-tabs__item--active::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 18rpx;
|
||||||
|
bottom: 0;
|
||||||
|
left: 18rpx;
|
||||||
|
height: 4rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: #ff8d62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-list {
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 28rpx 0;
|
||||||
|
border-top: 1px solid rgba(129, 141, 183, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item:first-child {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item--disabled {
|
||||||
|
opacity: 0.78;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__checkbox,
|
||||||
|
.bottom-bar__checkbox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
border: 2rpx solid rgba(255, 255, 255, 0.9);
|
||||||
|
background: #ffffff;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__checkbox {
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__checkbox--checked,
|
||||||
|
.bottom-bar__checkbox--checked {
|
||||||
|
border-color: #29d39c;
|
||||||
|
background: #29d39c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__checkbox--disabled {
|
||||||
|
border-color: rgba(205, 212, 235, 0.5);
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__checkbox-mark,
|
||||||
|
.bottom-bar__checkbox-mark {
|
||||||
|
font-size: 22rpx;
|
||||||
|
line-height: 1;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__status {
|
||||||
|
margin-left: 14rpx;
|
||||||
|
padding: 4rpx 14rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: rgba(255, 141, 98, 0.14);
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #ff8d62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__status--warning {
|
||||||
|
background: rgba(255, 141, 98, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__time {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: rgba(158, 170, 204, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__side {
|
||||||
|
margin-left: 18rpx;
|
||||||
|
padding-top: 2rpx;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__label {
|
||||||
|
display: block;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: rgba(240, 243, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-item__amount {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff8d62;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-empty {
|
||||||
|
margin: 22rpx 20rpx 30rpx;
|
||||||
|
padding: 70rpx 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(38, 45, 73, 0.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-empty__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-empty__desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: rgba(158, 170, 204, 0.86);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-bar {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 10;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 18rpx 20rpx calc(env(safe-area-inset-bottom) + 18rpx);
|
||||||
|
border-top: 1px solid rgba(129, 141, 183, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-bar__check-all {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-bar__check-all-text {
|
||||||
|
margin-left: 14rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-bar__button {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 170rpx;
|
||||||
|
height: 78rpx;
|
||||||
|
padding: 0 34rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
background: linear-gradient(135deg, #1ec5ff 0%, #179fe8 100%);
|
||||||
|
box-shadow: 0 14rpx 24rpx rgba(27, 179, 242, 0.22);
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-bar__button--disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,49 +1,83 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="asset-page asset-theme points-page">
|
<view class="asset-page asset-theme points-home-page">
|
||||||
<asset-page-shell title="积分转换" />
|
<asset-page-shell title="积分转换" />
|
||||||
|
|
||||||
<view class="asset-scroll points-scroll">
|
<view class="asset-scroll points-home-scroll">
|
||||||
<view class="hero-card">
|
<view class="hero-card">
|
||||||
<view class="hero-card__content">
|
<view class="hero-card__content">
|
||||||
<view class="hero-card__coin-row">
|
<view class="hero-card__coin-row">
|
||||||
<view class="hero-card__coin">
|
<view class="hero-card__coin">
|
||||||
<image
|
<image
|
||||||
class="hero-card__coin-image"
|
class="hero-card__coin-image"
|
||||||
:src="pageIcon('points')"
|
src="https://imgs.agrimedia.cn/bm-bmt/j-w.png"
|
||||||
mode="aspectFit"
|
mode="aspectFit"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<text class="hero-card__coin-text">积分</text>
|
<text class="hero-card__coin-text">积分</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="hero-card__label">可用积分:</text>
|
|
||||||
<text class="hero-card__value asset-number-font">{{ displayAvailablePoints }}</text>
|
<text class="hero-card__label">当前可用积分:</text>
|
||||||
|
|
||||||
|
<view class="hero-card__bottom">
|
||||||
|
<text class="hero-card__value asset-number-font">{{
|
||||||
|
detail.availablePoints
|
||||||
|
}}</text>
|
||||||
|
<view class="hero-card__button" @click="openConvertList">
|
||||||
|
积分转换
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="pending-card">
|
<picker
|
||||||
<text class="pending-card__label">未转换积分(释放中的积分)</text>
|
class="month-picker"
|
||||||
<text class="pending-card__value asset-number-font">{{ displayPendingPoints }}</text>
|
mode="selector"
|
||||||
</view>
|
:range="monthOptions"
|
||||||
|
:value="monthIndex"
|
||||||
<view class="tips-block">
|
@change="handleMonthChange"
|
||||||
<view
|
|
||||||
v-for="(tip, index) in detail.tips"
|
|
||||||
:key="tip"
|
|
||||||
class="tips-block__item"
|
|
||||||
>
|
>
|
||||||
<text class="tips-block__index asset-number-font">{{ index + 1 }}.</text>
|
<view class="month-picker__inner">
|
||||||
<text class="tips-block__text asset-number-font">{{ tip }}</text>
|
<text class="month-picker__text">{{
|
||||||
|
activeMonth
|
||||||
|
}}</text>
|
||||||
|
<text class="month-picker__arrow">▼</text>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
|
||||||
|
<view v-if="filteredRecords.length" class="record-list">
|
||||||
|
<view
|
||||||
|
v-for="item in filteredRecords"
|
||||||
|
:key="item.id + '-' + item.time"
|
||||||
|
class="record-card"
|
||||||
|
:class="{ 'record-card--clickable': item.detailAvailable }"
|
||||||
|
@click="openRecord(item)"
|
||||||
|
>
|
||||||
|
<view class="record-card__main">
|
||||||
|
<text class="record-card__title">{{ item.title }}</text>
|
||||||
|
<text class="record-card__time asset-number-font">{{
|
||||||
|
item.time
|
||||||
|
}}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="record-card__side">
|
||||||
|
<view class="record-card__amount-row">
|
||||||
|
<text
|
||||||
|
class="record-card__amount asset-number-font"
|
||||||
|
:class="'record-card__amount--' + item.amountTone"
|
||||||
|
>
|
||||||
|
{{ item.amount }}
|
||||||
|
</text>
|
||||||
|
<text v-if="item.detailAvailable" class="record-card__arrow"
|
||||||
|
>></text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="action-wrap">
|
<view v-else class="empty-card">
|
||||||
<view
|
<text class="empty-card__title">暂无转换记录</text>
|
||||||
class="action-button"
|
<text class="empty-card__desc">当前月份还没有积分转换明细。</text>
|
||||||
:class="{ 'action-button--disabled': !canSubmit || submitting }"
|
|
||||||
@click="submit"
|
|
||||||
>
|
|
||||||
{{ submitting ? "转换中..." : "转换可用积分" }}
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -51,10 +85,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AssetPageShell from "../../components/asset-page-shell.vue";
|
import AssetPageShell from "../../components/asset-page-shell.vue";
|
||||||
import {
|
import { fetchPointsConvertHome } from "../../api/assets";
|
||||||
fetchPointsConvertDetail,
|
|
||||||
submitAssetPointsConvert,
|
|
||||||
} from "../../api/assets";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -63,16 +94,30 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hasShown: false,
|
hasShown: false,
|
||||||
|
selectedMonth: "",
|
||||||
detail: {
|
detail: {
|
||||||
availablePoints: "0.00",
|
availablePoints: "0",
|
||||||
pendingPoints: "0",
|
records: [],
|
||||||
ids: [],
|
|
||||||
tips: [],
|
|
||||||
},
|
},
|
||||||
submitting: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
monthOptions() {
|
||||||
|
return this.buildMonthOptions();
|
||||||
|
},
|
||||||
|
monthIndex() {
|
||||||
|
const currentIndex = this.monthOptions.indexOf(this.activeMonth);
|
||||||
|
return currentIndex > -1 ? currentIndex : 0;
|
||||||
|
},
|
||||||
|
activeMonth() {
|
||||||
|
return this.selectedMonth || this.currentMonth();
|
||||||
|
},
|
||||||
|
filteredRecords() {
|
||||||
|
return Array.isArray(this.detail.records) ? this.detail.records : [];
|
||||||
|
},
|
||||||
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
this.selectedMonth = this.currentMonth();
|
||||||
this.loadPage(true);
|
this.loadPage(true);
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
|
@ -83,52 +128,45 @@ export default {
|
||||||
|
|
||||||
this.hasShown = true;
|
this.hasShown = true;
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
pendingPointsValue() {
|
|
||||||
return Number(this.detail.pendingPoints || 0);
|
|
||||||
},
|
|
||||||
canSubmit() {
|
|
||||||
return this.pendingPointsValue > 0;
|
|
||||||
},
|
|
||||||
displayAvailablePoints() {
|
|
||||||
return this.formatAmount(this.detail.availablePoints, 2);
|
|
||||||
},
|
|
||||||
displayPendingPoints() {
|
|
||||||
return this.formatAmount(this.detail.pendingPoints, 0);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
pageIcon(type) {
|
currentMonth() {
|
||||||
const iconMap = {
|
const currentDate = new Date();
|
||||||
points: "https://imgs.agrimedia.cn/bm-bmt/j-w.png",
|
return (
|
||||||
voucher: "https://imgs.agrimedia.cn/bm-bmt/quan-icon.png",
|
currentDate.getFullYear() +
|
||||||
coupon: "https://imgs.agrimedia.cn/bm-bmt/xiaofei-icon.png",
|
"-" +
|
||||||
power: "https://imgs.agrimedia.cn/bm-bmt/s.png",
|
String(currentDate.getMonth() + 1).padStart(2, "0")
|
||||||
bmt: "https://imgs.agrimedia.cn/bm-bmt/b.png",
|
);
|
||||||
};
|
|
||||||
|
|
||||||
return iconMap[type] || "";
|
|
||||||
},
|
},
|
||||||
formatAmount(value, digits) {
|
buildMonthOptions() {
|
||||||
const number = Number(value || 0);
|
const currentDate = new Date();
|
||||||
if (!Number.isFinite(number)) {
|
const monthList = [];
|
||||||
return digits > 0 ? Number(0).toFixed(digits) : "0";
|
|
||||||
|
for (let index = 0; index < 12; index += 1) {
|
||||||
|
const cursor = new Date(
|
||||||
|
currentDate.getFullYear(),
|
||||||
|
currentDate.getMonth() - index,
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
monthList.push(
|
||||||
|
cursor.getFullYear() +
|
||||||
|
"-" +
|
||||||
|
String(cursor.getMonth() + 1).padStart(2, "0"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (digits > 0) {
|
return monthList;
|
||||||
const fixed = number.toFixed(digits);
|
},
|
||||||
const parts = fixed.split(".");
|
handleMonthChange(event) {
|
||||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
const nextIndex = Number(
|
||||||
return parts.join(".");
|
event && event.detail ? event.detail.value : 0,
|
||||||
}
|
);
|
||||||
|
this.selectedMonth = this.monthOptions[nextIndex] || this.activeMonth;
|
||||||
return Math.floor(number)
|
this.loadPage();
|
||||||
.toString()
|
|
||||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
||||||
},
|
},
|
||||||
async loadPage(showLoading) {
|
async loadPage(showLoading) {
|
||||||
try {
|
try {
|
||||||
this.detail = await fetchPointsConvertDetail(
|
const result = await fetchPointsConvertHome(
|
||||||
|
this.activeMonth,
|
||||||
showLoading
|
showLoading
|
||||||
? {
|
? {
|
||||||
showLoading: true,
|
showLoading: true,
|
||||||
|
|
@ -136,6 +174,8 @@ export default {
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.detail = result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: error.message || "页面加载失败",
|
title: error.message || "页面加载失败",
|
||||||
|
|
@ -143,43 +183,30 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async submit() {
|
openConvertList() {
|
||||||
if (this.submitting) {
|
uni.navigateTo({
|
||||||
|
url: "/pages/assets/points-convert-list",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openRecord(item) {
|
||||||
|
if (!item || !item.detailAvailable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.canSubmit) {
|
const payload = encodeURIComponent(
|
||||||
uni.showToast({
|
JSON.stringify({
|
||||||
title: "暂无可转换积分",
|
id: item.id,
|
||||||
icon: "none",
|
sourceId: item.sourceId,
|
||||||
});
|
orderSn: item.orderSn,
|
||||||
return;
|
title: item.title,
|
||||||
}
|
amount: item.amount,
|
||||||
|
time: item.time,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
this.submitting = true;
|
uni.navigateTo({
|
||||||
|
url: "/pages/assets/points-convert-detail?payload=" + payload,
|
||||||
try {
|
|
||||||
const result = await submitAssetPointsConvert({
|
|
||||||
pendingPoints: this.pendingPointsValue,
|
|
||||||
ids: this.detail.ids,
|
|
||||||
}, {
|
|
||||||
showLoading: true,
|
|
||||||
loadingText: "转换中",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
uni.showToast({
|
|
||||||
title: result.message || "转换成功",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
this.loadPage();
|
|
||||||
} catch (error) {
|
|
||||||
uni.showToast({
|
|
||||||
title: error.message || "转换失败",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
this.submitting = false;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -189,41 +216,37 @@ export default {
|
||||||
@import "../../styles/tokens.scss";
|
@import "../../styles/tokens.scss";
|
||||||
@import "../../styles/common.scss";
|
@import "../../styles/common.scss";
|
||||||
|
|
||||||
.points-page {
|
.points-home-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #191e32;
|
background: #191e32;
|
||||||
}
|
}
|
||||||
|
|
||||||
.points-scroll {
|
.points-home-scroll {
|
||||||
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 10rpx 14rpx calc(env(safe-area-inset-bottom) + 36rpx);
|
padding: 10rpx 14rpx calc(env(safe-area-inset-bottom) + 36rpx);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-card,
|
|
||||||
.pending-card {
|
|
||||||
border-radius: 8rpx;
|
|
||||||
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-card {
|
.hero-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 240rpx;
|
|
||||||
padding: 24rpx 28rpx;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
min-height: 248rpx;
|
||||||
|
padding: 24rpx 28rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
background: #242944 url("https://imgs.agrimedia.cn/bm-bmt/jifen-header.png")
|
background: #242944 url("https://imgs.agrimedia.cn/bm-bmt/jifen-header.png")
|
||||||
no-repeat center top / 100% 240rpx;
|
no-repeat center top / 100% 248rpx;
|
||||||
|
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.16);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-card__content {
|
.hero-card__content {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-card__coin-row {
|
.hero-card__coin-row,
|
||||||
|
.hero-card__bottom,
|
||||||
|
.record-card,
|
||||||
|
.record-card__amount-row,
|
||||||
|
.month-picker__inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
@ -252,86 +275,153 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-card__label {
|
.hero-card__label {
|
||||||
|
display: block;
|
||||||
margin-top: 38rpx;
|
margin-top: 38rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #9ba7ce;
|
color: rgba(233, 239, 255, 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-card__value {
|
.hero-card__bottom {
|
||||||
margin-top: 8rpx;
|
|
||||||
font-size: 48rpx;
|
|
||||||
font-weight: 800;
|
|
||||||
line-height: 1.08;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pending-card {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 20rpx;
|
|
||||||
padding: 30rpx 26rpx;
|
|
||||||
background: rgba(59, 49, 67, 0.92);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pending-card__label,
|
|
||||||
.pending-card__value {
|
|
||||||
font-size: 26rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #ff885d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pending-card__value {
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-block {
|
|
||||||
margin-top: 20rpx;
|
|
||||||
padding: 0 2rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-block__item {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
margin-top: 10rpx;
|
margin-top: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips-block__item:first-child {
|
.hero-card__value {
|
||||||
margin-top: 0;
|
max-width: 360rpx;
|
||||||
|
font-size: 58rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1.05;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-right: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tips-block__index,
|
.hero-card__button {
|
||||||
.tips-block__text {
|
display: inline-flex;
|
||||||
font-size: 24rpx;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.75;
|
|
||||||
color: rgba(173, 184, 216, 0.82);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-block__index {
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-right: 6rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-wrap {
|
|
||||||
margin-top: auto;
|
|
||||||
padding: 120rpx 24rpx 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-button {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 90rpx;
|
min-width: 166rpx;
|
||||||
|
height: 48rpx;
|
||||||
border-radius: 999rpx;
|
border-radius: 999rpx;
|
||||||
background: linear-gradient(135deg, #22c2ff 0%, #159de6 100%);
|
background: linear-gradient(135deg, #1ec5ff 0%, #179fe8 100%);
|
||||||
box-shadow: 0 16rpx 30rpx rgba(31, 169, 243, 0.2);
|
box-shadow: 0 14rpx 24rpx rgba(27, 179, 242, 0.22);
|
||||||
font-size: 32rpx;
|
font-size: 26rpx;
|
||||||
font-weight: 700;
|
font-weight: 500;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-button--disabled {
|
.month-picker {
|
||||||
opacity: 0.56;
|
display: inline-block;
|
||||||
|
margin-top: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.month-picker__inner {
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 210rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
padding: 0 18rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
background: #4a5174;
|
||||||
|
}
|
||||||
|
|
||||||
|
.month-picker__text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.month-picker__arrow {
|
||||||
|
font-size: 18rpx;
|
||||||
|
color: rgba(255, 255, 255, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-list {
|
||||||
|
margin-top: 22rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card,
|
||||||
|
.empty-card {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
background: #242944;
|
||||||
|
box-shadow: 0 12rpx 24rpx rgba(8, 13, 30, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card {
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 26rpx 28rpx;
|
||||||
|
margin-top: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card--clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__time {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: rgba(158, 170, 204, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__side {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__amount-row {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__amount {
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__amount--increase {
|
||||||
|
color: #ff8b63;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__amount--decrease {
|
||||||
|
color: #20ddb0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-card__arrow {
|
||||||
|
margin-left: 16rpx;
|
||||||
|
font-size: 38rpx;
|
||||||
|
line-height: 1;
|
||||||
|
color: rgba(255, 255, 255, 0.96);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-card {
|
||||||
|
margin-top: 22rpx;
|
||||||
|
padding: 60rpx 28rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-card__title {
|
||||||
|
display: block;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-card__desc {
|
||||||
|
display: block;
|
||||||
|
margin-top: 14rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: rgba(158, 170, 204, 0.86);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="asset-page asset-theme wallet-page">
|
<view class="asset-page asset-theme wallet-page">
|
||||||
<view class="wallet-nav">
|
<asset-page-shell title="钱包地址" />
|
||||||
<view class="wallet-nav__side">
|
|
||||||
<view class="wallet-nav__back" @click="handleBack">
|
|
||||||
<text class="wallet-nav__back-icon">‹</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<text class="wallet-nav__title">钱包地址</text>
|
|
||||||
<view class="wallet-nav__side"></view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="asset-scroll wallet-scroll">
|
<view class="asset-scroll wallet-scroll">
|
||||||
<view class="wallet-panel">
|
<view class="wallet-panel">
|
||||||
|
|
@ -80,11 +72,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import AssetPageShell from "../../components/asset-page-shell.vue";
|
||||||
import WalletActionPopup from "../../components/wallet-action-popup.vue";
|
import WalletActionPopup from "../../components/wallet-action-popup.vue";
|
||||||
import { fetchWalletDetail, deleteAssetWallet } from "../../api/assets";
|
import { fetchWalletDetail, deleteAssetWallet } from "../../api/assets";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
AssetPageShell,
|
||||||
WalletActionPopup,
|
WalletActionPopup,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -192,40 +186,6 @@ export default {
|
||||||
background: #191e32;
|
background: #191e32;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wallet-nav {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 120rpx 1fr 120rpx;
|
|
||||||
align-items: center;
|
|
||||||
padding: calc(env(safe-area-inset-top) + 12rpx) 14rpx 12rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wallet-nav__side {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wallet-nav__back {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 56rpx;
|
|
||||||
height: 56rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wallet-nav__back-icon {
|
|
||||||
margin-top: -4rpx;
|
|
||||||
font-size: 56rpx;
|
|
||||||
line-height: 1;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wallet-nav__title {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: 700;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wallet-scroll {
|
.wallet-scroll {
|
||||||
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
min-height: calc(100vh - env(safe-area-inset-top) - 104rpx);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,6 @@
|
||||||
class="stat-card"
|
class="stat-card"
|
||||||
:class="'stat-card--' + item.accent"
|
:class="'stat-card--' + item.accent"
|
||||||
>
|
>
|
||||||
<view
|
|
||||||
class="stat-card__icon-box"
|
|
||||||
:class="'stat-card__icon-box--' + item.accent"
|
|
||||||
>
|
|
||||||
<image
|
|
||||||
class="stat-card__icon-image"
|
|
||||||
:src="statIcon(item.key)"
|
|
||||||
mode="aspectFit"
|
|
||||||
></image>
|
|
||||||
</view>
|
|
||||||
<view class="stat-card__body">
|
<view class="stat-card__body">
|
||||||
<text class="stat-card__label">{{ item.title }}</text>
|
<text class="stat-card__label">{{ item.title }}</text>
|
||||||
<view class="stat-card__value-row">
|
<view class="stat-card__value-row">
|
||||||
|
|
@ -55,6 +45,7 @@
|
||||||
v-for="item in overview.quickAssets"
|
v-for="item in overview.quickAssets"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
class="asset-mini-card"
|
class="asset-mini-card"
|
||||||
|
:class="'asset-mini-card--' + item.accent"
|
||||||
@click="openQuickAsset(item)"
|
@click="openQuickAsset(item)"
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
|
|
@ -63,13 +54,6 @@
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
<view class="asset-mini-card__head">
|
<view class="asset-mini-card__head">
|
||||||
<view class="asset-mini-card__icon">
|
|
||||||
<image
|
|
||||||
class="asset-mini-card__icon-image"
|
|
||||||
:src="quickAssetIcon(item.key)"
|
|
||||||
mode="aspectFit"
|
|
||||||
></image>
|
|
||||||
</view>
|
|
||||||
<text class="asset-mini-card__label">{{ item.title }}</text>
|
<text class="asset-mini-card__label">{{ item.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="asset-mini-card__value asset-number-font">{{ item.value }}</text>
|
<text class="asset-mini-card__value asset-number-font">{{ item.value }}</text>
|
||||||
|
|
@ -148,14 +132,6 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
statIcon(key) {
|
|
||||||
const iconMap = {
|
|
||||||
"wallet-bmt": "https://imgs.agrimedia.cn/bm-bmt/hong-l.png",
|
|
||||||
ticker: "https://imgs.agrimedia.cn/bm-bmt/hong-r.png",
|
|
||||||
};
|
|
||||||
|
|
||||||
return iconMap[key] || "";
|
|
||||||
},
|
|
||||||
quickAssetIcon(key) {
|
quickAssetIcon(key) {
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
points: "https://imgs.agrimedia.cn/bm-bmt/jifen-icon.png",
|
points: "https://imgs.agrimedia.cn/bm-bmt/jifen-icon.png",
|
||||||
|
|
@ -214,7 +190,7 @@ export default {
|
||||||
points: "/pages/assets/ledger?type=points",
|
points: "/pages/assets/ledger?type=points",
|
||||||
voucher: "/pages/assets/ledger?type=voucher",
|
voucher: "/pages/assets/ledger?type=voucher",
|
||||||
coupon: "/pages/assets/ledger?type=coupon",
|
coupon: "/pages/assets/ledger?type=coupon",
|
||||||
power: "/pages/assets/ledger?type=power-flow",
|
power: "/pages/assets/ledger?type=power",
|
||||||
};
|
};
|
||||||
|
|
||||||
const targetUrl = urlMap[item.key];
|
const targetUrl = urlMap[item.key];
|
||||||
|
|
@ -478,7 +454,9 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
padding: 18rpx 20rpx;
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
padding: 0rpx 20rpx;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
box-shadow: 0 12rpx 24rpx rgba(10, 16, 37, 0.16);
|
box-shadow: 0 12rpx 24rpx rgba(10, 16, 37, 0.16);
|
||||||
background: rgba(35, 45, 79, 0.9);
|
background: rgba(35, 45, 79, 0.9);
|
||||||
|
|
@ -491,6 +469,22 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.asset-mini-card--blue {
|
||||||
|
background: linear-gradient(135deg, #10acee 0%, #1aa4ff 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-mini-card--green {
|
||||||
|
background: linear-gradient(135deg, #25d8a4 0%, #36e08f 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-mini-card--orange {
|
||||||
|
background: linear-gradient(135deg, #ff8d58 0%, #ff7d7d 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.asset-mini-card--violet {
|
||||||
|
background: linear-gradient(135deg, #a667f3 0%, #b27cff 100%);
|
||||||
|
}
|
||||||
|
|
||||||
.asset-mini-card__head,
|
.asset-mini-card__head,
|
||||||
.asset-mini-card__value {
|
.asset-mini-card__value {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -499,9 +493,8 @@ export default {
|
||||||
|
|
||||||
.asset-mini-card__head {
|
.asset-mini-card__head {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
min-width: 0;
|
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.asset-mini-card__icon {
|
.asset-mini-card__icon {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue