Compare commits

...

3 Commits

Author SHA1 Message Date
946f60e5c3 Merge branch 'main' of http://1.117.67.95:3000/team/tydata-admin
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CI / CI OK (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
2025-12-27 13:55:47 +08:00
b392f9cf0d addanalysis 2025-12-27 13:51:08 +08:00
a718ac7874 price analysis 2025-12-26 15:18:31 +08:00
17 changed files with 1161 additions and 158 deletions

View File

@@ -1,3 +0,0 @@
# 每次 git pull 之后, 安装依赖
pnpm install

View File

@@ -138,6 +138,12 @@ export namespace AgentApi {
withdraw_no?: string;
}
// 提现统计数据
export interface WithdrawalStatistics {
total_withdrawal_amount: number;
today_withdrawal_amount: number;
}
// 代理上级抽佣相关接口
export interface AgentCommissionDeductionListItem {
id: number;
@@ -472,6 +478,15 @@ async function reviewBankCardWithdrawal(
);
}
/**
* 获取提现统计数据
*/
async function getWithdrawalStatistics() {
return requestClient.get<AgentApi.WithdrawalStatistics>(
'/agent/agent-withdrawal/statistics',
);
}
export {
getAgentCommissionDeductionList,
getAgentCommissionList,
@@ -483,7 +498,6 @@ export {
getAgentRewardList,
getAgentWithdrawalList,
getMembershipRechargeOrderList,
reviewBankCardWithdrawal,
updateAgentMembershipConfig,
updateAgentProductionConfig,
};

View File

@@ -11,6 +11,7 @@ export namespace OrderApi {
payment_platform: 'alipay' | 'appleiap' | 'wechat';
payment_scene: 'app' | 'h5' | 'mini_program' | 'public_account';
amount: number;
sales_cost: number;
status: 'closed' | 'failed' | 'paid' | 'pending' | 'refunded';
query_state: 'cleaned' | 'failed' | 'pending' | 'processing' | 'success';
create_time: string;
@@ -34,6 +35,20 @@ export namespace OrderApi {
refund_no: string;
amount: number;
}
// 退款统计数据
export interface RefundStatistics {
total_refund_amount: number;
today_refund_amount: number;
}
// 收入统计数据
export interface IncomeStatistics {
total_revenue_amount: number;
today_revenue_amount: number;
total_profit_amount: number;
today_profit_amount: number;
}
}
/**
@@ -57,4 +72,18 @@ async function refundOrder(id: number, data: OrderApi.RefundOrderRequest) {
);
}
export { getOrderList, refundOrder };
/**
* 获取退款统计数据
*/
async function getRefundStatistics() {
return requestClient.get<OrderApi.RefundStatistics>('/order/refund-statistics');
}
/**
* 获取收入统计数据
*/
async function getIncomeStatistics() {
return requestClient.get<OrderApi.IncomeStatistics>('/order/revenue-statistics');
}
export { getOrderList, refundOrder, getRefundStatistics, getIncomeStatistics };

View File

@@ -7,6 +7,7 @@ export namespace FeatureApi {
id: number;
api_id: string;
name: string;
cost_price: number;
create_time: string;
update_time: string;
}
@@ -19,11 +20,13 @@ export namespace FeatureApi {
export interface CreateFeatureRequest {
api_id: string;
name: string;
cost_price: number;
}
export interface UpdateFeatureRequest {
api_id?: string;
name?: string;
cost_price?: number;
}
export interface FeatureExampleItem {

View File

@@ -61,6 +61,10 @@ export namespace ProductApi {
export interface UpdateProductFeaturesRequest {
features: ProductFeatureItem[];
}
export interface UpdateProductFeaturesResponse {
success: boolean;
}
}
/**

View File

@@ -5,74 +5,209 @@ import { onMounted, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { statsHistory, statsTotal } from '#/api/promotion/analytics';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
series: [
{
areaStyle: {},
data: [
120, 300, 500, 800, 1200, 1800, 2500, 3000, 2800, 2600, 2400, 2200,
2000, 1800, 1600, 1400, 1200, 1000, 800, 600, 400, 200, 100, 50, 30,
20, 10, 5, 2, 1,
],
itemStyle: {
color: '#5ab1ef',
},
smooth: true,
type: 'line',
name: '访问量',
// 获取30天前的日期
const getDateString = (daysAgo: number) => {
const date = new Date();
date.setDate(date.getDate() - daysAgo);
return date.toISOString().split('T')[0];
};
onMounted(async () => {
try {
// 获取趋势数据
const endDate = getDateString(0); // 今天
const startDate = getDateString(29); // 29天前
const trendData = await statsHistory({ start_date: startDate, end_date: endDate });
// 获取统计数据
const statsData = await statsTotal();
// 准备图表数据
const dates = Array.from({ length: 30 }).map((_, index) => {
const date = new Date();
date.setDate(date.getDate() - 29 + index);
return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' });
});
// 如果有历史数据,使用历史数据;否则使用模拟数据
let clickData = Array(30).fill(0);
if (trendData && trendData.length > 0) {
// 将历史数据按日期排序并映射到数组
const sortedData = trendData.sort((a, b) =>
new Date(a.stats_date).getTime() - new Date(b.stats_date).getTime()
);
sortedData.forEach((item) => {
const itemDate = new Date(item.stats_date);
const today = new Date();
const daysDiff = Math.floor((today.getTime() - itemDate.getTime()) / (1000 * 60 * 60 * 24));
if (daysDiff >= 0 && daysDiff < 30) {
// 使用实际日期索引
clickData[29 - daysDiff] = item.click_count || 0;
}
});
} else {
// 没有历史数据时,使用统计数据生成模拟数据
const todayClickCount = statsData?.today_click_count || 0;
const totalClickCount = statsData?.total_click_count || 0;
// 简单的线性分布模拟数据
for (let i = 0; i < 30; i++) {
// 最后一天使用今日数据,其他天按比例分布
if (i === 29) {
clickData[i] = todayClickCount;
} else {
// 按指数衰减模拟历史数据
clickData[i] = Math.max(0, Math.floor(todayClickCount * Math.exp(-0.05 * (29 - i))));
}
}
// 确保总和不超过总计数
const sum = clickData.reduce((a, b) => a + b, 0);
if (sum > totalClickCount && totalClickCount > 0) {
const ratio = totalClickCount / sum;
clickData = clickData.map(val => Math.floor(val * ratio));
}
}
// 计算Y轴最大值
const maxValue = Math.max(...clickData) || 10;
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
],
tooltip: {
axisPointer: {
lineStyle: {
color: '#5ab1ef',
width: 1,
series: [
{
areaStyle: {},
data: clickData,
itemStyle: {
color: '#5ab1ef',
},
smooth: true,
type: 'line',
name: '推广访问量',
},
],
tooltip: {
axisPointer: {
lineStyle: {
color: '#5ab1ef',
width: 1,
},
},
trigger: 'axis',
formatter: (params: any) => {
const param = params[0];
return `${param.axisValue}<br/>${param.seriesName}: ${param.value}`;
},
},
trigger: 'axis',
},
xAxis: {
axisTick: {
show: false,
},
boundaryGap: false,
data: Array.from({ length: 30 }).map(
(_item, index) => `Day ${index + 1}`,
),
splitLine: {
lineStyle: {
type: 'solid',
width: 1,
},
show: true,
},
type: 'category',
},
yAxis: [
{
xAxis: {
axisTick: {
show: false,
},
max: 3000,
splitArea: {
boundaryGap: false,
data: dates,
splitLine: {
lineStyle: {
type: 'solid',
width: 1,
},
show: true,
},
splitNumber: 4,
type: 'value',
type: 'category',
},
],
});
yAxis: [
{
axisTick: {
show: false,
},
max: Math.ceil(maxValue * 1.2), // 比最大值大20%作为Y轴上限
splitArea: {
show: true,
},
splitNumber: 4,
type: 'value',
},
],
});
} catch (error) {
console.error('获取推广趋势数据失败:', error);
// 发生错误时显示默认图表
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
series: [
{
areaStyle: {},
data: Array(30).fill(0),
itemStyle: {
color: '#5ab1ef',
},
smooth: true,
type: 'line',
name: '推广访问量',
},
],
tooltip: {
axisPointer: {
lineStyle: {
color: '#5ab1ef',
width: 1,
},
},
trigger: 'axis',
},
xAxis: {
axisTick: {
show: false,
},
boundaryGap: false,
data: Array.from({ length: 30 }).map((_, index) => {
const date = new Date();
date.setDate(date.getDate() - 29 + index);
return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' });
}),
splitLine: {
lineStyle: {
type: 'solid',
width: 1,
},
show: true,
},
type: 'category',
},
yAxis: [
{
axisTick: {
show: false,
},
max: 10,
splitArea: {
show: true,
},
splitNumber: 4,
type: 'value',
},
],
});
}
});
</script>

View File

@@ -5,49 +5,153 @@ import { onMounted, ref } from 'vue';
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
import { getOrderList } from '#/api/order/order';
const chartRef = ref<EchartsUIType>();
const { renderEcharts } = useEcharts(chartRef);
onMounted(() => {
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
series: [
{
barMaxWidth: 80,
data: [
30, 20, 33, 50, 32, 42, 32, 21, 30, 51, 60, 32, 48, 40, 35, 28, 22,
18, 15, 10, 8, 6, 4, 2, 1, 1, 0, 0, 0, 0,
],
type: 'bar',
name: '订单数',
onMounted(async () => {
try {
// 准备图表数据
const dates = Array.from({ length: 30 }).map((_, index) => {
const date = new Date();
date.setDate(date.getDate() - 29 + index);
return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' });
});
// 准备日期数组,用于查询订单数据
const queryDates = Array.from({ length: 30 }).map((_, index) => {
const date = new Date();
date.setDate(date.getDate() - 29 + index);
return date.toISOString().split('T')[0]; // YYYY-MM-DD格式
});
// 获取每日订单数据
const orderDataPromises = queryDates.map(async (date) => {
try {
// 获取当天的开始和结束时间
const startTime = `${date} 00:00:00`;
const endTime = `${date} 23:59:59`;
// 获取当天的订单数据
const response = await getOrderList({
page: 1,
pageSize: 1,
create_time_start: startTime,
create_time_end: endTime
});
return response.total || 0;
} catch (error) {
console.error(`获取${date}的订单数据失败:`, error);
return 0;
}
});
// 等待所有请求完成
const orderData = await Promise.all(orderDataPromises);
// 计算Y轴最大值
const maxValue = Math.max(...orderData) || 10;
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
],
tooltip: {
axisPointer: {
lineStyle: {
width: 1,
series: [
{
data: orderData,
type: 'line',
name: '订单数',
smooth: true,
itemStyle: {
color: '#4f9cff',
},
areaStyle: {
opacity: 0.3,
color: '#4f9cff',
},
},
],
tooltip: {
axisPointer: {
lineStyle: {
width: 1,
},
},
trigger: 'axis',
formatter: (params: any) => {
const param = params[0];
return `${param.axisValue}<br/>${param.seriesName}: ${param.value}`;
},
},
trigger: 'axis',
},
xAxis: {
data: Array.from({ length: 30 }).map(
(_item, index) => `Day ${index + 1}`,
),
type: 'category',
},
yAxis: {
max: 80,
splitNumber: 4,
type: 'value',
},
});
xAxis: {
data: dates,
type: 'category',
boundaryGap: false,
},
yAxis: {
max: Math.ceil(maxValue * 1.2), // 比最大值大20%作为Y轴上限
splitNumber: 4,
type: 'value',
},
});
} catch (error) {
console.error('获取订单趋势数据失败:', error);
// 发生错误时显示默认图表
renderEcharts({
grid: {
bottom: 0,
containLabel: true,
left: '1%',
right: '1%',
top: '2%',
},
series: [
{
data: Array(30).fill(0),
type: 'line',
name: '订单数',
smooth: true,
itemStyle: {
color: '#4f9cff',
},
areaStyle: {
opacity: 0.3,
color: '#4f9cff',
},
},
],
tooltip: {
axisPointer: {
lineStyle: {
width: 1,
},
},
trigger: 'axis',
},
xAxis: {
data: Array.from({ length: 30 }).map((_, index) => {
const date = new Date();
date.setDate(date.getDate() - 29 + index);
return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' });
}),
type: 'category',
boundaryGap: false,
},
yAxis: {
max: 10,
splitNumber: 4,
type: 'value',
},
});
}
});
</script>

View File

@@ -14,42 +14,65 @@ import {
SvgDownloadIcon,
} from '@vben/icons';
import { onMounted, ref } from 'vue';
import AnalyticsTrends from './analytics-trends.vue';
import AnalyticsVisitsData from './analytics-visits-data.vue';
import AnalyticsVisitsSales from './analytics-visits-sales.vue';
import AnalyticsVisitsSource from './analytics-visits-source.vue';
import AnalyticsVisits from './analytics-visits.vue';
const overviewItems: AnalysisOverviewItem[] = [
import { getAgentList, getWithdrawalStatistics } from '#/api/agent';
import { getOrderList, getRefundStatistics, getIncomeStatistics } from '#/api/order/order';
import { getPlatformUserList } from '#/api/platform-user';
// 初始化概览数据
const overviewItems = ref<AnalysisOverviewItem[]>([
{
icon: SvgCardIcon,
title: '平台用户数',
totalTitle: '总用户数',
totalValue: 120_000,
value: 2000,
title: '用户数',
value: 0,
todaytitle: '今日新增用户数',
todayValue: 0,
Subtitle: '总代理数',
SubValue: 0,
todaySubtitle: '今日新增代理数',
todaySubValue: 0,
},
{
icon: SvgCakeIcon,
title: '推广访问量',
totalTitle: '总推广访问量',
totalValue: 500_000,
value: 20_000,
title: '总订单数',
value: 0,
todaytitle: '今日新增订单数',
todayValue: 0,
Subtitle: '代理总订单量',
SubValue: 0,
todaySubtitle: '今日新增代理订单量',
todaySubValue: 0,
},
{
icon: SvgDownloadIcon,
title: '产品数量',
totalTitle: '总产品数量',
totalValue: 120,
value: 8,
title: '总收入',
value: 0,
todaytitle: '今日新增收入',
todayValue: 0,
Subtitle: '总利润',
SubValue: 0,
todaySubtitle: '今日新增利润',
todaySubValue: 0,
},
{
icon: SvgBellIcon,
title: '代理数量',
totalTitle: '总代理数量',
totalValue: 5000,
value: 500,
title: '总提现金额',
value: 0,
todaytitle: '今日新增提现金额',
todayValue: 0,
Subtitle: '总退款金额',
SubValue: 0,
todaySubtitle: '今日新增退款金额',
todaySubValue: 0,
},
];
]);
const chartTabs: TabOption[] = [
{
@@ -61,13 +84,147 @@ const chartTabs: TabOption[] = [
value: 'visits',
},
];
// 获取统计数据
async function fetchStatistics() {
try {
// 获取今日的开始和结束时间
const today = new Date();
// 将时间格式化为后端期望的格式 (YYYY-MM-DD HH:MM:SS)
const startTime = new Date(today.getFullYear(), today.getMonth(), today.getDate()).toISOString().replace('T', ' ').substring(0, 19);
const endTime = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1).toISOString().replace('T', ' ').substring(0, 19);
// 获取平台用户数据(总数)
const platformUserResponse = await getPlatformUserList({ page: 1, pageSize: 1 });
const platformUserTotal = platformUserResponse.total || 0;
// 获取今日新增用户数
// 由于平台用户API不支持时间过滤我们需要获取更多数据并在前端过滤
const newUserResponse = await getPlatformUserList({ page: 1, pageSize: 1000 });
const newUserCount = newUserResponse.items?.filter(user => {
const userCreateTime = new Date(user.create_time);
return userCreateTime >= new Date(startTime) && userCreateTime < new Date(endTime);
}).length || 0;
// 获取订单数据
const orderResponse = await getOrderList({ page: 1, pageSize: 1 });
const orderTotal = orderResponse.total || 0;
// 获取代理订单数据
const agentOrderResponse = await getOrderList({ page: 1, pageSize: 1, is_agent_order: true });
const agentOrderTotal = agentOrderResponse.total || 0;
// 获取今日新增订单数
const todayOrderResponse = await getOrderList({
page: 1,
pageSize: 1000,
create_time_start: startTime,
create_time_end: endTime
});
const todayOrderTotal = todayOrderResponse.total || 0;
// 获取今日新增代理订单数
const todayAgentOrderResponse = await getOrderList({
page: 1,
pageSize: 1000,
is_agent_order: true,
create_time_start: startTime,
create_time_end: endTime
});
const todayAgentOrderTotal = todayAgentOrderResponse.total || 0;
// Product data is no longer needed for order statistics
// 获取代理数据(总数)
const agentResponse = await getAgentList({ page: 1, pageSize: 1 });
const agentTotal = agentResponse.total || 0;
// 获取今日新增代理数
const newAgentResponse = await getAgentList({
page: 1,
pageSize: 100,
create_time_start: startTime,
create_time_end: endTime
});
const newAgentCount = newAgentResponse.total || 0;
// 获取提现统计数据
const withdrawalStatsResponse = await getWithdrawalStatistics();
const totalWithdrawalAmount = withdrawalStatsResponse.total_withdrawal_amount || 0;
const todayWithdrawalAmount = withdrawalStatsResponse.today_withdrawal_amount || 0;
// 获取退款统计数据
const refundStatsResponse = await getRefundStatistics();
const totalRefundAmount = refundStatsResponse.total_refund_amount || 0;
const todayRefundAmount = refundStatsResponse.today_refund_amount || 0;
// 获取收入统计数据
const incomeStatsResponse = await getIncomeStatistics();
const totalIncome = incomeStatsResponse.total_revenue_amount || 0;
const todayIncome = incomeStatsResponse.today_revenue_amount || 0;
const totalProfit = incomeStatsResponse.total_profit_amount || 0;
const todayProfit = incomeStatsResponse.today_profit_amount || 0;
// 更新概览数据
overviewItems.value = [
{
icon: SvgCardIcon,
title: '总用户数',
value: platformUserTotal,
todaytitle: '今日新增用户数',
todayValue: newUserCount,
Subtitle: '总代理数',
SubValue: agentTotal,
todaySubtitle: '今日新增代理数',
todaySubValue: newAgentCount,
},
{
icon: SvgCakeIcon,
title: '总订单数',
value: orderTotal,
todaytitle: '今日新增订单数',
todayValue: todayOrderTotal,
Subtitle: '总代理订单量',
SubValue: agentOrderTotal,
todaySubtitle: '今日新增代理订单量',
todaySubValue: todayAgentOrderTotal,
},
{
icon: SvgDownloadIcon,
title: '总收入',
value: totalIncome,
todaytitle: '今日新增收入',
todayValue: todayIncome,
Subtitle: '总利润',
SubValue: totalProfit,
todaySubtitle: '今日新增利润',
todaySubValue: todayProfit,
},
{
icon: SvgBellIcon,
title: '总提现金额',
value: totalWithdrawalAmount,
todaytitle: '今日新增提现金额',
todayValue: todayWithdrawalAmount,
Subtitle: '总退款金额',
SubValue: totalRefundAmount,
todaySubtitle: '今日新增退款金额',
todaySubValue: todayRefundAmount,
},
];
} catch (error) {
console.error('获取统计数据失败:', error);
}
}
// 组件挂载时获取数据
onMounted(() => {
fetchStatistics();
});
</script>
<template>
<div class="p-5">
<div class="mb-4 ml-4 text-lg text-gray-500">
该数据为演示模拟生成不为真实数据
</div>
<AnalysisOverview :items="overviewItems" />
<AnalysisChartsTabs :tabs="chartTabs" class="mt-5">
<template #trends>

View File

@@ -53,6 +53,14 @@ export function useColumns<T = OrderApi.Order>(
return sceneMap[row.payment_scene] || row.payment_scene;
},
},
{
field: 'sales_cost',
title: '成本价',
width: 120,
formatter: ({ row }) => {
return `¥${row.sales_cost.toFixed(2)}`;
},
},
{
field: 'amount',
title: '金额',

View File

@@ -17,6 +17,27 @@ export function useFormSchema(): VbenFormSchema[] {
label: '描述',
rules: 'required',
},
{
component: 'InputNumber',
fieldName: 'cost_price',
label: '成本价',
rules: 'required',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
formatter: (value: number) => {
// 格式化为带千分位分隔符的货币
const parts = value.toString().split('.');
parts[0] = (parts[0] || '0').replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return `¥ ${parts.join('.')}`;
},
parser: (value: string) => {
// 移除货币符号和千分位分隔符
return value.replace(/[¥,\s]/g, '');
},
},
},
];
}
@@ -33,6 +54,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
fieldName: 'name',
label: '描述',
},
];
}
@@ -51,6 +73,18 @@ export function useColumns<T = FeatureApi.FeatureItem>(
title: '描述',
minWidth: 200,
},
{
field: 'cost_price',
title: '成本价',
minWidth: 120,
formatter: ({ cellValue }) => {
// 格式化为带千分位分隔符的货币
const value = cellValue?.toFixed(2) || '0.00';
const parts = value.split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return `¥ ${parts.join('.')}`;
},
},
{
field: 'create_time',
title: '创建时间',

View File

@@ -28,6 +28,7 @@ import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getFeatureList } from '#/api/product-manage/feature';
import {
getProductFeatureList,
updateProduct,
updateProductFeatures,
} from '#/api/product-manage/product';
@@ -71,11 +72,28 @@ const [Modal, modalApi] = useVbenModal({
// 更新产品模块关联
await updateProductFeatures(productId, { features });
message.success('保存成功');
// 计算关联模块的总成本(只计算启用的模块)
let totalCost = 0;
const enabledFeatures = tempFeatureList.value.filter(item => item.enable === 1);
// 使用缓存的模块数据计算总成本
for (const feature of enabledFeatures) {
const featureDetail = allFeaturesCache.value.find(f => f.id === feature.feature_id);
if (featureDetail) {
totalCost += featureDetail.cost_price || 0;
}
}
// 更新产品成本价
await updateProduct(productId, { cost_price: totalCost });
message.success(`保存成功,产品成本已更新为: ¥${totalCost.toFixed(2)}`);
emit('success');
modalApi.close(); // 保存成功后关闭Modal
return true;
} catch {
} catch (error) {
console.error('保存失败:', error);
message.error('保存失败');
return false;
}
@@ -84,6 +102,8 @@ const [Modal, modalApi] = useVbenModal({
const loading = ref(false);
const tempFeatureList = ref<TempFeatureItem[]>([]);
// 存储模块详细信息,用于成本计算
const allFeaturesCache = ref<FeatureApi.FeatureItem[]>([]);
// 表格配置
const [Grid] = useVbenVxeGrid({
@@ -219,6 +239,7 @@ async function loadFeatureList() {
loading.value = true;
try {
// 获取产品已关联的模块列表
const res = await getProductFeatureList(productId);
// 转换为临时数据格式
let tempList = res.map((item) => ({
@@ -237,6 +258,11 @@ async function loadFeatureList() {
.map((item, idx) => ({ ...item, sort: idx + 1 }));
}
tempFeatureList.value = tempList;
// 获取并缓存所有模块数据(用于成本计算)
const allFeaturesRes = await getFeatureList({ page: 1, pageSize: 1000 });
allFeaturesCache.value = allFeaturesRes.items || [];
initSortable();
} finally {
loading.value = false;
@@ -326,6 +352,22 @@ function handleRemoveFeature(record: TempFeatureItem) {
},
});
}
// 计算已启用模块的总成本
function calculateTotalCost() {
let totalCost = 0;
const enabledFeatures = tempFeatureList.value.filter(item => item.enable === 1);
// 使用缓存的模块数据计算总成本
for (const feature of enabledFeatures) {
const featureDetail = allFeaturesCache.value.find(f => f.id === feature.feature_id);
if (featureDetail) {
totalCost += featureDetail.cost_price || 0;
}
}
return totalCost;
}
</script>
<template>
@@ -343,6 +385,12 @@ function handleRemoveFeature(record: TempFeatureItem) {
<!-- 右侧已关联模块列表 -->
<div class="flex-1">
<div class="mb-2 text-base font-medium">已关联模块</div>
<div class="mb-2 p-3 bg-gray-50 rounded">
<div class="flex justify-between items-center">
<span class="text-sm font-medium">已启用模块总成本</span>
<span class="text-lg font-bold text-red-600">¥{{ calculateTotalCost().toFixed(2) }}</span>
</div>
</div>
<div class="mb-4 text-sm text-gray-500">
提示可以通过拖拽行来调整模块顺序通过开关控制模块的启用状态和重要程度
</div>

View File

@@ -81,6 +81,7 @@
"autoprefixer": "catalog:",
"cross-env": "catalog:",
"cspell": "catalog:",
"cssnano": "^7.1.2",
"happy-dom": "catalog:",
"husky": "catalog:",
"is-ci": "catalog:",

View File

@@ -4,7 +4,6 @@ import type { AnalysisOverviewItem } from '../typing';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
VbenCountToAnimator,
@@ -26,32 +25,38 @@ withDefaults(defineProps<Props>(), {
<template>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
<template v-for="item in items" :key="item.title">
<Card :title="item.title" class="w-full">
<CardHeader>
<CardTitle class="text-xl">{{ item.title }}</CardTitle>
</CardHeader>
<CardContent class="flex items-center justify-between">
<VbenCountToAnimator
:end-val="item.value"
:start-val="1"
class="text-xl"
prefix=""
:decimals="item.decimals ?? 0"
/>
<VbenIcon :icon="item.icon" class="size-8 flex-shrink-0" />
</CardContent>
<CardFooter class="justify-between">
<span>{{ item.totalTitle }}</span>
<VbenCountToAnimator
:end-val="item.totalValue"
:start-val="1"
prefix=""
:decimals="item.decimals ?? 0"
/>
</CardFooter>
</Card>
</template>
<Card v-for="(item, index) in items" :key="index" class="relative overflow-hidden">
<CardHeader class="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle class="text-sm font-medium">
{{ item.title }}
</CardTitle>
<VbenIcon :icon="item.icon" class="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div class="text-2xl font-bold">
<VbenCountToAnimator :end-val="item.value" />
</div>
<p class="text-xs text-muted-foreground">
{{ item.todaytitle }}
<span class="font-medium text-foreground">
+<VbenCountToAnimator :end-val="item.todayValue" />
</span>
</p>
<div class="mt-3 border-t pt-3">
<p class="text-xs text-muted-foreground flex justify-between">
<span>{{ item.Subtitle }}</span>
<span class="font-medium text-foreground">
<VbenCountToAnimator :end-val="item.SubValue" />
</span>
</p>
<p class="text-xs text-muted-foreground flex justify-between mt-1">
<span>{{ item.todaySubtitle }}</span>
<span class="font-medium text-foreground">
+<VbenCountToAnimator :end-val="item.todaySubValue" />
</span>
</p>
</div>
</CardContent>
</Card>
</div>
</template>

View File

@@ -3,10 +3,13 @@ import type { Component } from 'vue';
interface AnalysisOverviewItem {
icon: Component | string;
title: string;
totalTitle: string;
totalValue: number;
value: number;
decimals?: number;
todaytitle: string;
todayValue: number;
Subtitle: string;
SubValue: number;
todaySubtitle: string;
todaySubValue: number;
}
interface WorkbenchProjectItem {

View File

@@ -43,10 +43,12 @@
"@vben/request": "workspace:*",
"@vben/stores": "workspace:*",
"@vben/styles": "workspace:*",
"@vben/tailwind-config": "workspace:*",
"@vben/types": "workspace:*",
"@vben/utils": "workspace:*",
"@vueuse/core": "catalog:",
"ant-design-vue": "catalog:",
"cssnano": "catalog:",
"dayjs": "catalog:",
"pinia": "catalog:",
"vue": "catalog:",

View File

@@ -1 +1,12 @@
export { default } from '@vben/tailwind-config/postcss';
import config from '@vben/tailwind-config';
export default {
plugins: {
autoprefixer: {},
'postcss-antd-fixes': { prefixes: ['ant', 'el'] },
'postcss-import': {},
'postcss-preset-env': {},
tailwindcss: { config },
'tailwindcss/nesting': {},
},
};

458
pnpm-lock.yaml generated
View File

@@ -593,6 +593,9 @@ importers:
cspell:
specifier: 'catalog:'
version: 8.19.4
cssnano:
specifier: ^7.1.2
version: 7.1.2(postcss@8.5.3)
happy-dom:
specifier: 'catalog:'
version: 16.8.1
@@ -1757,6 +1760,9 @@ importers:
'@vben/styles':
specifier: workspace:*
version: link:../packages/styles
'@vben/tailwind-config':
specifier: workspace:*
version: link:../internal/tailwind-config
'@vben/types':
specifier: workspace:*
version: link:../packages/types
@@ -1769,6 +1775,9 @@ importers:
ant-design-vue:
specifier: 'catalog:'
version: 4.2.6(vue@3.5.13(typescript@5.8.3))
cssnano:
specifier: 'catalog:'
version: 7.0.6(postcss@8.5.3)
dayjs:
specifier: 'catalog:'
version: 1.11.13
@@ -5120,6 +5129,10 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
baseline-browser-mapping@2.9.11:
resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==}
hasBin: true
better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
engines: {node: '>=4'}
@@ -5159,6 +5172,11 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
browserslist@4.28.1:
resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-crc32@1.0.0:
resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==}
engines: {node: '>=8.0.0'}
@@ -5243,6 +5261,9 @@ packages:
caniuse-lite@1.0.30001702:
resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==}
caniuse-lite@1.0.30001761:
resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==}
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -5400,6 +5421,10 @@ packages:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
@@ -5680,6 +5705,12 @@ packages:
engines: {node: '>=4'}
hasBin: true
cssnano-preset-default@7.0.10:
resolution: {integrity: sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
cssnano-preset-default@7.0.6:
resolution: {integrity: sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
@@ -5692,12 +5723,24 @@ packages:
peerDependencies:
postcss: ^8.4.31
cssnano-utils@5.0.1:
resolution: {integrity: sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
cssnano@7.0.6:
resolution: {integrity: sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
cssnano@7.1.2:
resolution: {integrity: sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
csso@5.0.5:
resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
@@ -6017,6 +6060,9 @@ packages:
electron-to-chromium@1.5.113:
resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==}
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
emoji-regex-xs@1.0.0:
resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
@@ -7952,6 +7998,9 @@ packages:
node-releases@2.0.19:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
node-releases@2.0.27:
resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
nopt@7.2.1:
resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==}
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
@@ -8363,12 +8412,24 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-colormin@7.0.5:
resolution: {integrity: sha512-ekIBP/nwzRWhEMmIxHHbXHcMdzd1HIUzBECaj5KEdLz9DVP2HzT065sEhvOx1dkLjYW7jyD0CngThx6bpFi2fA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-convert-values@7.0.4:
resolution: {integrity: sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-convert-values@7.0.8:
resolution: {integrity: sha512-+XNKuPfkHTCEo499VzLMYn94TiL3r9YqRE3Ty+jP7UX4qjewUONey1t7CG21lrlTLN07GtGM8MqFVp86D4uKJg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-custom-media@11.0.5:
resolution: {integrity: sha512-SQHhayVNgDvSAdX9NQ/ygcDQGEY+aSF4b/96z7QUX6mqL5yl/JgG/DywcF6fW9XbnCRE+aVYk+9/nqGuzOPWeQ==}
engines: {node: '>=18'}
@@ -8399,24 +8460,48 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-discard-comments@7.0.5:
resolution: {integrity: sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-discard-duplicates@7.0.1:
resolution: {integrity: sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-discard-duplicates@7.0.2:
resolution: {integrity: sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-discard-empty@7.0.0:
resolution: {integrity: sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-discard-empty@7.0.1:
resolution: {integrity: sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-discard-overridden@7.0.0:
resolution: {integrity: sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-discard-overridden@7.0.1:
resolution: {integrity: sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-double-position-gradients@6.0.0:
resolution: {integrity: sha512-JkIGah3RVbdSEIrcobqj4Gzq0h53GG4uqDPsho88SgY84WnpkTpI0k50MFK/sX7XqVisZ6OqUfFnoUO6m1WWdg==}
engines: {node: '>=18'}
@@ -8507,36 +8592,72 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-merge-longhand@7.0.5:
resolution: {integrity: sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-merge-rules@7.0.4:
resolution: {integrity: sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-merge-rules@7.0.7:
resolution: {integrity: sha512-njWJrd/Ms6XViwowaaCc+/vqhPG3SmXn725AGrnl+BgTuRPEacjiLEaGq16J6XirMJbtKkTwnt67SS+e2WGoew==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-minify-font-values@7.0.0:
resolution: {integrity: sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-minify-font-values@7.0.1:
resolution: {integrity: sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-minify-gradients@7.0.0:
resolution: {integrity: sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-minify-gradients@7.0.1:
resolution: {integrity: sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-minify-params@7.0.2:
resolution: {integrity: sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-minify-params@7.0.5:
resolution: {integrity: sha512-FGK9ky02h6Ighn3UihsyeAH5XmLEE2MSGH5Tc4tXMFtEDx7B+zTG6hD/+/cT+fbF7PbYojsmmWjyTwFwW1JKQQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-minify-selectors@7.0.4:
resolution: {integrity: sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-minify-selectors@7.0.5:
resolution: {integrity: sha512-x2/IvofHcdIrAm9Q+p06ZD1h6FPcQ32WtCRVodJLDR+WMn8EVHI1kvLxZuGKz/9EY5nAmI6lIQIrpo4tBy5+ug==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-nested@5.0.6:
resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==}
engines: {node: '>=12.0'}
@@ -8567,54 +8688,108 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-normalize-charset@7.0.1:
resolution: {integrity: sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-display-values@7.0.0:
resolution: {integrity: sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-display-values@7.0.1:
resolution: {integrity: sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-positions@7.0.0:
resolution: {integrity: sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-positions@7.0.1:
resolution: {integrity: sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-repeat-style@7.0.0:
resolution: {integrity: sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-repeat-style@7.0.1:
resolution: {integrity: sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-string@7.0.0:
resolution: {integrity: sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-string@7.0.1:
resolution: {integrity: sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-timing-functions@7.0.0:
resolution: {integrity: sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-timing-functions@7.0.1:
resolution: {integrity: sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-unicode@7.0.2:
resolution: {integrity: sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-unicode@7.0.5:
resolution: {integrity: sha512-X6BBwiRxVaFHrb2WyBMddIeB5HBjJcAaUHyhLrM2FsxSq5TFqcHSsK7Zu1otag+o0ZphQGJewGH1tAyrD0zX1Q==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-url@7.0.0:
resolution: {integrity: sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-url@7.0.1:
resolution: {integrity: sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-normalize-whitespace@7.0.0:
resolution: {integrity: sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-normalize-whitespace@7.0.1:
resolution: {integrity: sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-opacity-percentage@3.0.0:
resolution: {integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==}
engines: {node: '>=18'}
@@ -8627,6 +8802,12 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-ordered-values@7.0.2:
resolution: {integrity: sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-overflow-shorthand@6.0.0:
resolution: {integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==}
engines: {node: '>=18'}
@@ -8662,12 +8843,24 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-reduce-initial@7.0.5:
resolution: {integrity: sha512-RHagHLidG8hTZcnr4FpyMB2jtgd/OcyAazjMhoy5qmWJOx1uxKh4ntk0Pb46ajKM0rkf32lRH4C8c9qQiPR6IA==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-reduce-transforms@7.0.0:
resolution: {integrity: sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-reduce-transforms@7.0.1:
resolution: {integrity: sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-replace-overflow-wrap@4.0.0:
resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==}
peerDependencies:
@@ -8723,12 +8916,24 @@ packages:
peerDependencies:
postcss: ^8.4.31
postcss-svgo@7.1.0:
resolution: {integrity: sha512-KnAlfmhtoLz6IuU3Sij2ycusNs4jPW+QoFE5kuuUOK8awR6tMxZQrs5Ey3BUz7nFCzT3eqyFgqkyrHiaU2xx3w==}
engines: {node: ^18.12.0 || ^20.9.0 || >= 18}
peerDependencies:
postcss: ^8.4.32
postcss-unique-selectors@7.0.3:
resolution: {integrity: sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.31
postcss-unique-selectors@7.0.4:
resolution: {integrity: sha512-pmlZjsmEAG7cHd7uK3ZiNSW6otSZ13RHuZ/4cDN/bVglS5EpF2r2oxY99SuOHa8m7AWoBCelTS3JPpzsIs8skQ==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
postcss-value-parser@4.2.0:
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
@@ -9553,6 +9758,12 @@ packages:
peerDependencies:
postcss: ^8.4.31
stylehacks@7.0.7:
resolution: {integrity: sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g==}
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
peerDependencies:
postcss: ^8.4.32
stylelint-config-html@1.1.0:
resolution: {integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==}
engines: {node: ^12 || >=14}
@@ -9660,6 +9871,11 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
svgo@4.0.0:
resolution: {integrity: sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==}
engines: {node: '>=16'}
hasBin: true
synckit@0.11.3:
resolution: {integrity: sha512-szhWDqNNI9etJUvbZ1/cx1StnZx8yMmFxme48SwR4dty4ioSY50KEZlpv0qAfgc1fpRzuh9hBXEzoCpJ779dLg==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -10116,6 +10332,12 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
update-notifier@7.3.1:
resolution: {integrity: sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==}
engines: {node: '>=18'}
@@ -10925,7 +11147,7 @@ snapshots:
'@babel/core': 7.26.9
'@babel/helper-compilation-targets': 7.26.5
'@babel/helper-plugin-utils': 7.26.5
debug: 4.4.0
debug: 4.4.3
lodash.debounce: 4.0.8
resolve: 1.22.10
transitivePeerDependencies:
@@ -14453,6 +14675,8 @@ snapshots:
base64-js@1.5.1: {}
baseline-browser-mapping@2.9.11: {}
better-path-resolve@1.0.0:
dependencies:
is-windows: 1.0.2
@@ -14500,6 +14724,14 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.24.4)
browserslist@4.28.1:
dependencies:
baseline-browser-mapping: 2.9.11
caniuse-lite: 1.0.30001761
electron-to-chromium: 1.5.267
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
buffer-crc32@1.0.0: {}
buffer-equal-constant-time@1.0.1: {}
@@ -14600,13 +14832,15 @@ snapshots:
caniuse-api@3.0.0:
dependencies:
browserslist: 4.24.4
browserslist: 4.28.1
caniuse-lite: 1.0.30001702
lodash.memoize: 4.1.2
lodash.uniq: 4.5.0
caniuse-lite@1.0.30001702: {}
caniuse-lite@1.0.30001761: {}
ccount@2.0.1: {}
chai@5.2.0:
@@ -14788,6 +15022,8 @@ snapshots:
commander@10.0.1: {}
commander@11.1.0: {}
commander@12.1.0: {}
commander@13.1.0: {}
@@ -15097,6 +15333,40 @@ snapshots:
cssesc@3.0.0: {}
cssnano-preset-default@7.0.10(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
css-declaration-sorter: 7.2.0(postcss@8.5.3)
cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-calc: 10.1.1(postcss@8.5.3)
postcss-colormin: 7.0.5(postcss@8.5.3)
postcss-convert-values: 7.0.8(postcss@8.5.3)
postcss-discard-comments: 7.0.5(postcss@8.5.3)
postcss-discard-duplicates: 7.0.2(postcss@8.5.3)
postcss-discard-empty: 7.0.1(postcss@8.5.3)
postcss-discard-overridden: 7.0.1(postcss@8.5.3)
postcss-merge-longhand: 7.0.5(postcss@8.5.3)
postcss-merge-rules: 7.0.7(postcss@8.5.3)
postcss-minify-font-values: 7.0.1(postcss@8.5.3)
postcss-minify-gradients: 7.0.1(postcss@8.5.3)
postcss-minify-params: 7.0.5(postcss@8.5.3)
postcss-minify-selectors: 7.0.5(postcss@8.5.3)
postcss-normalize-charset: 7.0.1(postcss@8.5.3)
postcss-normalize-display-values: 7.0.1(postcss@8.5.3)
postcss-normalize-positions: 7.0.1(postcss@8.5.3)
postcss-normalize-repeat-style: 7.0.1(postcss@8.5.3)
postcss-normalize-string: 7.0.1(postcss@8.5.3)
postcss-normalize-timing-functions: 7.0.1(postcss@8.5.3)
postcss-normalize-unicode: 7.0.5(postcss@8.5.3)
postcss-normalize-url: 7.0.1(postcss@8.5.3)
postcss-normalize-whitespace: 7.0.1(postcss@8.5.3)
postcss-ordered-values: 7.0.2(postcss@8.5.3)
postcss-reduce-initial: 7.0.5(postcss@8.5.3)
postcss-reduce-transforms: 7.0.1(postcss@8.5.3)
postcss-svgo: 7.1.0(postcss@8.5.3)
postcss-unique-selectors: 7.0.4(postcss@8.5.3)
cssnano-preset-default@7.0.6(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
@@ -15135,12 +15405,22 @@ snapshots:
dependencies:
postcss: 8.5.3
cssnano-utils@5.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
cssnano@7.0.6(postcss@8.5.3):
dependencies:
cssnano-preset-default: 7.0.6(postcss@8.5.3)
lilconfig: 3.1.3
postcss: 8.5.3
cssnano@7.1.2(postcss@8.5.3):
dependencies:
cssnano-preset-default: 7.0.10(postcss@8.5.3)
lilconfig: 3.1.3
postcss: 8.5.3
csso@5.0.5:
dependencies:
css-tree: 2.2.1
@@ -15408,6 +15688,8 @@ snapshots:
electron-to-chromium@1.5.113: {}
electron-to-chromium@1.5.267: {}
emoji-regex-xs@1.0.0: {}
emoji-regex@10.4.0: {}
@@ -17396,7 +17678,7 @@ snapshots:
dependencies:
autoprefixer: 10.4.21(postcss@8.5.3)
citty: 0.1.6
cssnano: 7.0.6(postcss@8.5.3)
cssnano: 7.1.2(postcss@8.5.3)
defu: 6.1.4
esbuild: 0.24.0
jiti: 1.21.7
@@ -17594,6 +17876,8 @@ snapshots:
node-releases@2.0.19: {}
node-releases@2.0.27: {}
nopt@7.2.1:
dependencies:
abbrev: 2.0.0
@@ -18001,12 +18285,26 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-colormin@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
caniuse-api: 3.0.0
colord: 2.9.3
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-convert-values@7.0.4(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-convert-values@7.0.8(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-custom-media@11.0.5(postcss@8.5.3):
dependencies:
'@csstools/cascade-layer-name-parser': 2.0.4(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
@@ -18042,18 +18340,35 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-discard-comments@7.0.5(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
postcss-discard-duplicates@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-discard-duplicates@7.0.2(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-discard-empty@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-discard-empty@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-discard-overridden@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-discard-overridden@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-double-position-gradients@6.0.0(postcss@8.5.3):
dependencies:
'@csstools/postcss-progressive-custom-properties': 4.0.0(postcss@8.5.3)
@@ -18140,6 +18455,12 @@ snapshots:
postcss-value-parser: 4.2.0
stylehacks: 7.0.4(postcss@8.5.3)
postcss-merge-longhand@7.0.5(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
stylehacks: 7.0.7(postcss@8.5.3)
postcss-merge-rules@7.0.4(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
@@ -18148,11 +18469,24 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-merge-rules@7.0.7(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
caniuse-api: 3.0.0
cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-selector-parser: 7.1.0
postcss-minify-font-values@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-font-values@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-gradients@7.0.0(postcss@8.5.3):
dependencies:
colord: 2.9.3
@@ -18160,6 +18494,13 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-gradients@7.0.1(postcss@8.5.3):
dependencies:
colord: 2.9.3
cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-params@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
@@ -18167,12 +18508,25 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-params@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-minify-selectors@7.0.4(postcss@8.5.3):
dependencies:
cssesc: 3.0.0
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-minify-selectors@7.0.5(postcss@8.5.3):
dependencies:
cssesc: 3.0.0
postcss: 8.5.3
postcss-selector-parser: 7.1.0
postcss-nested@5.0.6(postcss@8.5.3):
dependencies:
postcss: 8.5.3
@@ -18199,47 +18553,92 @@ snapshots:
dependencies:
postcss: 8.5.3
postcss-normalize-charset@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-normalize-display-values@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-display-values@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-positions@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-positions@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-repeat-style@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-repeat-style@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-string@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-string@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-timing-functions@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-timing-functions@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-unicode@7.0.2(postcss@8.5.3):
dependencies:
browserslist: 4.24.4
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-unicode@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-url@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-url@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-whitespace@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-normalize-whitespace@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-opacity-percentage@3.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
@@ -18250,6 +18649,12 @@ snapshots:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-ordered-values@7.0.2(postcss@8.5.3):
dependencies:
cssnano-utils: 5.0.1(postcss@8.5.3)
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-overflow-shorthand@6.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
@@ -18342,11 +18747,22 @@ snapshots:
caniuse-api: 3.0.0
postcss: 8.5.3
postcss-reduce-initial@7.0.5(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
caniuse-api: 3.0.0
postcss: 8.5.3
postcss-reduce-transforms@7.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-reduce-transforms@7.0.1(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
postcss-replace-overflow-wrap@4.0.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
@@ -18395,11 +18811,22 @@ snapshots:
postcss-value-parser: 4.2.0
svgo: 3.3.2
postcss-svgo@7.1.0(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-value-parser: 4.2.0
svgo: 4.0.0
postcss-unique-selectors@7.0.3(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-selector-parser: 6.1.2
postcss-unique-selectors@7.0.4(postcss@8.5.3):
dependencies:
postcss: 8.5.3
postcss-selector-parser: 7.1.0
postcss-value-parser@4.2.0: {}
postcss@8.5.3:
@@ -18838,8 +19265,7 @@ snapshots:
optionalDependencies:
'@parcel/watcher': 2.5.1
sax@1.4.1:
optional: true
sax@1.4.1: {}
scroll-into-view-if-needed@2.2.31:
dependencies:
@@ -19254,6 +19680,12 @@ snapshots:
postcss: 8.5.3
postcss-selector-parser: 6.1.2
stylehacks@7.0.7(postcss@8.5.3):
dependencies:
browserslist: 4.28.1
postcss: 8.5.3
postcss-selector-parser: 7.1.0
stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.18.0(typescript@5.8.3)):
dependencies:
postcss-html: 1.8.0
@@ -19407,6 +19839,16 @@ snapshots:
csso: 5.0.5
picocolors: 1.1.1
svgo@4.0.0:
dependencies:
commander: 11.1.0
css-select: 5.1.0
css-tree: 3.1.0
css-what: 6.1.0
csso: 5.0.5
picocolors: 1.1.1
sax: 1.4.1
synckit@0.11.3:
dependencies:
'@pkgr/core': 0.2.1
@@ -19888,6 +20330,12 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
update-browserslist-db@1.2.3(browserslist@4.28.1):
dependencies:
browserslist: 4.28.1
escalade: 3.2.0
picocolors: 1.1.1
update-notifier@7.3.1:
dependencies:
boxen: 8.0.1