feat: 新增报告结果查看并完善产品模块配置
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
CodeQL / Analyze (${{ matrix.language }}) (none, 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
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
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
CodeQL / Analyze (${{ matrix.language }}) (none, 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
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
This commit is contained in:
parent
d3609c21c0
commit
db606f10b3
@ -1,59 +1 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace OrderApi {
|
||||
export interface Order {
|
||||
id: number;
|
||||
order_no: string;
|
||||
platform_order_id: string;
|
||||
product_name: string;
|
||||
payment_platform: 'alipay' | 'appleiap' | 'wechat';
|
||||
payment_scene: 'app' | 'h5' | 'mini_program' | 'public_account';
|
||||
amount: number;
|
||||
status: 'closed' | 'failed' | 'paid' | 'pending' | 'refunded';
|
||||
create_time: string;
|
||||
pay_time: null | string;
|
||||
refund_time: null | string;
|
||||
is_promotion: 0 | 1;
|
||||
}
|
||||
|
||||
export interface OrderList {
|
||||
total: number;
|
||||
items: Order[];
|
||||
}
|
||||
|
||||
export interface RefundOrderRequest {
|
||||
refund_amount: number;
|
||||
refund_reason: string;
|
||||
}
|
||||
|
||||
export interface RefundOrderResponse {
|
||||
status: string;
|
||||
refund_no: string;
|
||||
amount: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表数据
|
||||
*/
|
||||
async function getOrderList(params: Recordable<any>) {
|
||||
return requestClient.get<OrderApi.OrderList>('/order/list', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
* @param id 订单 ID
|
||||
* @param data 退款请求数据
|
||||
*/
|
||||
async function refundOrder(id: number, data: OrderApi.RefundOrderRequest) {
|
||||
return requestClient.post<OrderApi.RefundOrderResponse>(
|
||||
`/order/refund/${id}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
export { getOrderList, refundOrder };
|
||||
export * from './order';
|
||||
|
60
apps/web-antd/src/api/order/order.ts
Normal file
60
apps/web-antd/src/api/order/order.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace OrderApi {
|
||||
export interface Order {
|
||||
id: number;
|
||||
order_no: string;
|
||||
platform_order_id: string;
|
||||
product_name: string;
|
||||
payment_platform: 'alipay' | 'appleiap' | 'wechat';
|
||||
payment_scene: 'app' | 'h5' | 'mini_program' | 'public_account';
|
||||
amount: number;
|
||||
status: 'closed' | 'failed' | 'paid' | 'pending' | 'refunded';
|
||||
query_state: 'failed' | 'pending' | 'processing' | 'success';
|
||||
create_time: string;
|
||||
pay_time: null | string;
|
||||
refund_time: null | string;
|
||||
is_promotion: 0 | 1;
|
||||
}
|
||||
|
||||
export interface OrderList {
|
||||
total: number;
|
||||
items: Order[];
|
||||
}
|
||||
|
||||
export interface RefundOrderRequest {
|
||||
refund_amount: number;
|
||||
refund_reason: string;
|
||||
}
|
||||
|
||||
export interface RefundOrderResponse {
|
||||
status: string;
|
||||
refund_no: string;
|
||||
amount: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单列表数据
|
||||
*/
|
||||
async function getOrderList(params: Recordable<any>) {
|
||||
return requestClient.get<OrderApi.OrderList>('/order/list', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
* @param id 订单 ID
|
||||
* @param data 退款请求数据
|
||||
*/
|
||||
async function refundOrder(id: number, data: OrderApi.RefundOrderRequest) {
|
||||
return requestClient.post<OrderApi.RefundOrderResponse>(
|
||||
`/order/refund/${id}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
export { getOrderList, refundOrder };
|
50
apps/web-antd/src/api/order/query.ts
Normal file
50
apps/web-antd/src/api/order/query.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace OrderQueryApi {
|
||||
export interface QueryItem {
|
||||
feature: Recordable<any>;
|
||||
data: Recordable<any>;
|
||||
}
|
||||
|
||||
export interface QueryDetail {
|
||||
id: number;
|
||||
order_id: number;
|
||||
user_id: number;
|
||||
product_name: string;
|
||||
query_params: Recordable<any>;
|
||||
query_data: QueryItem[];
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
query_state: string;
|
||||
}
|
||||
|
||||
export interface GetQueryDetailRequest {
|
||||
order_id: number;
|
||||
}
|
||||
|
||||
export interface GetQueryDetailResponse {
|
||||
id: number;
|
||||
order_id: number;
|
||||
user_id: number;
|
||||
product_name: string;
|
||||
query_params: Recordable<any>;
|
||||
query_data: QueryItem[];
|
||||
create_time: string;
|
||||
update_time: string;
|
||||
query_state: string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单查询详情
|
||||
* @param orderId 订单ID
|
||||
*/
|
||||
async function getOrderQueryDetail(orderId: number) {
|
||||
return requestClient.get<OrderQueryApi.GetQueryDetailResponse>(
|
||||
`/query/detail/${orderId}`,
|
||||
);
|
||||
}
|
||||
|
||||
export { getOrderQueryDetail };
|
@ -77,6 +77,20 @@ export function useColumns<T = OrderApi.Order>(
|
||||
title: '支付状态',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
cellRender: {
|
||||
name: 'CellTag',
|
||||
options: [
|
||||
{ value: 'pending', color: 'warning', label: '查询中' },
|
||||
{ value: 'success', color: 'success', label: '查询成功' },
|
||||
{ value: 'failed', color: 'error', label: '查询失败' },
|
||||
{ value: 'processing', color: 'warning', label: '查询中' },
|
||||
],
|
||||
},
|
||||
field: 'query_state',
|
||||
title: '查询状态',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
field: 'create_time',
|
||||
title: '创建时间',
|
||||
@ -121,12 +135,19 @@ export function useColumns<T = OrderApi.Order>(
|
||||
return row.status !== 'paid';
|
||||
},
|
||||
},
|
||||
{
|
||||
code: 'query',
|
||||
text: '查询结果',
|
||||
disabled: (row: OrderApi.Order) => {
|
||||
return row.query_state !== 'success';
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
field: 'operation',
|
||||
fixed: 'right',
|
||||
title: '操作',
|
||||
width: 100,
|
||||
width: 180,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import type {
|
||||
} from '#/adapter/vxe-table';
|
||||
import type { OrderApi } from '#/api/order';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page, useVbenDrawer } from '@vben/common-ui';
|
||||
|
||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
@ -56,8 +58,19 @@ const [RefundDrawer, refundDrawerApi] = useVbenDrawer({
|
||||
destroyOnClose: true,
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function onActionClick(e: OnActionClickParams<OrderApi.Order>) {
|
||||
switch (e.code) {
|
||||
case 'query': {
|
||||
router.push({
|
||||
name: 'OrderQueryDetail',
|
||||
params: {
|
||||
id: e.row.id,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'refund': {
|
||||
onRefund(e.row);
|
||||
break;
|
||||
|
253
apps/web-antd/src/views/order/query.vue
Normal file
253
apps/web-antd/src/views/order/query.vue
Normal file
@ -0,0 +1,253 @@
|
||||
<script lang="ts" setup>
|
||||
import type { JsonViewerAction } from '@vben/common-ui';
|
||||
|
||||
import type { OrderQueryApi } from '#/api/order/query';
|
||||
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { JsonViewer, Page } from '@vben/common-ui';
|
||||
import { MdiArrowLeft } from '@vben/icons';
|
||||
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Collapse,
|
||||
Descriptions,
|
||||
message,
|
||||
Tag,
|
||||
} from 'ant-design-vue';
|
||||
|
||||
import { getOrderQueryDetail } from '#/api/order/query';
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const orderId = Number(route.params.id);
|
||||
const loading = ref(false);
|
||||
const queryDetail = ref<OrderQueryApi.QueryDetail>();
|
||||
|
||||
// 查询状态配置
|
||||
const queryStateConfig = [
|
||||
{ value: 'pending', color: 'warning', label: '查询中' },
|
||||
{ value: 'success', color: 'success', label: '查询成功' },
|
||||
{ value: 'failed', color: 'error', label: '查询失败' },
|
||||
{ value: 'processing', color: 'warning', label: '查询中' },
|
||||
] as const;
|
||||
|
||||
// 获取查询状态配置
|
||||
function getQueryStateConfig(state: string) {
|
||||
return (
|
||||
queryStateConfig.find((item) => item.value === state) || {
|
||||
color: 'default',
|
||||
label: state,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// 字段名称映射
|
||||
const fieldNameMap: Record<string, string> = {
|
||||
// 基础字段
|
||||
name: '姓名',
|
||||
id_card: '身份证号',
|
||||
mobile: '手机号',
|
||||
code: '验证码',
|
||||
// 企业相关
|
||||
ent_name: '企业名称',
|
||||
ent_code: '统一社会信用代码',
|
||||
// 婚姻相关
|
||||
name_man: '男方姓名',
|
||||
id_card_man: '男方身份证号',
|
||||
name_woman: '女方姓名',
|
||||
id_card_woman: '女方身份证号',
|
||||
// 车辆相关
|
||||
car_type: '车辆类型',
|
||||
car_license: '车牌号',
|
||||
vin_code: '车架号',
|
||||
car_driving_permit: '行驶证号',
|
||||
// 银行卡相关
|
||||
bank_card: '银行卡号',
|
||||
// 学历相关
|
||||
certificate_number: '证书编号',
|
||||
// 日期相关
|
||||
start_date: '开始日期',
|
||||
};
|
||||
|
||||
// 获取字段显示名称
|
||||
function getFieldDisplayName(key: string): string {
|
||||
return fieldNameMap[key] || key;
|
||||
}
|
||||
|
||||
// 返回订单管理页面
|
||||
function handleBack() {
|
||||
router.push('/order');
|
||||
}
|
||||
|
||||
// 获取查询详情
|
||||
async function fetchQueryDetail() {
|
||||
if (!orderId) return;
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getOrderQueryDetail(orderId);
|
||||
queryDetail.value = res;
|
||||
} catch {
|
||||
message.error('获取查询详情失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function handleCopied(_event: JsonViewerAction) {
|
||||
message.success('已复制JSON');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchQueryDetail();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page>
|
||||
<div class="p-4">
|
||||
<div class="mb-4 flex items-center">
|
||||
<Button @click="handleBack">
|
||||
<template #icon><MdiArrowLeft /></template>
|
||||
返回订单管理
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card :loading="loading" class="mb-4">
|
||||
<template #title>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-lg font-medium">订单查询详情</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-gray-500">查询状态:</span>
|
||||
<Tag
|
||||
v-if="queryDetail"
|
||||
:color="getQueryStateConfig(queryDetail.query_state).color"
|
||||
>
|
||||
{{ getQueryStateConfig(queryDetail.query_state).label }}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="queryDetail">
|
||||
<Descriptions :column="2" bordered>
|
||||
<Descriptions.Item label="订单ID">
|
||||
{{ queryDetail.order_id }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="用户ID">
|
||||
{{ queryDetail.user_id }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="产品名称">
|
||||
{{ queryDetail.product_name }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="创建时间">
|
||||
{{ queryDetail.create_time }}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="更新时间">
|
||||
{{ queryDetail.update_time }}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</template>
|
||||
</Card>
|
||||
|
||||
<template v-if="queryDetail">
|
||||
<Card class="mb-4">
|
||||
<template #title>
|
||||
<span class="text-lg font-medium">查询参数</span>
|
||||
</template>
|
||||
<template v-if="queryDetail.query_params">
|
||||
<Descriptions :column="2" bordered>
|
||||
<Descriptions.Item
|
||||
v-for="(value, key) in queryDetail.query_params"
|
||||
:key="key"
|
||||
:label="getFieldDisplayName(key)"
|
||||
>
|
||||
{{ value }}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</template>
|
||||
<div v-else class="text-gray-500">暂无查询参数</div>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<template #title>
|
||||
<span class="text-lg font-medium">查询数据</span>
|
||||
</template>
|
||||
<template v-if="queryDetail.query_data?.length">
|
||||
<Collapse
|
||||
:default-active-key="
|
||||
queryDetail.query_data.map((_, index) => index)
|
||||
"
|
||||
>
|
||||
<Collapse.Panel
|
||||
v-for="(item, index) in queryDetail.query_data"
|
||||
:key="index"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-lg font-medium">{{
|
||||
item.feature.featureName
|
||||
}}</span>
|
||||
<Tag color="blue">API: {{ item.data.apiID }}</Tag>
|
||||
</div>
|
||||
<Tag
|
||||
:color="
|
||||
String(item.data.success) === 'true'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
>
|
||||
{{
|
||||
String(item.data.success) === 'true'
|
||||
? '查询成功'
|
||||
: '查询失败'
|
||||
}}
|
||||
</Tag>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="grid gap-4">
|
||||
<div v-if="item.data.data">
|
||||
<div class="mb-2 font-medium">查询结果:</div>
|
||||
<JsonViewer
|
||||
:value="item.data.data"
|
||||
copyable
|
||||
:expand-depth="2"
|
||||
boxed
|
||||
@copied="handleCopied"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-gray-500">
|
||||
查询时间: {{ item.data.timestamp }}
|
||||
</div>
|
||||
</div>
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
</template>
|
||||
<div v-else class="py-4 text-center text-gray-500">暂无查询数据</div>
|
||||
</Card>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Card>
|
||||
<div class="py-8 text-center text-gray-500">
|
||||
{{ loading ? '加载中...' : '暂无查询数据' }}
|
||||
</div>
|
||||
</Card>
|
||||
</template>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.ant-collapse-header) {
|
||||
padding: 12px 16px !important;
|
||||
}
|
||||
|
||||
:deep(.ant-collapse-content-box) {
|
||||
padding: 16px !important;
|
||||
}
|
||||
</style>
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts" setup>
|
||||
import type { TableColumnsType } from 'ant-design-vue';
|
||||
// @ts-expect-error: sortablejs 没有类型声明
|
||||
import type { SortableEvent } from 'sortablejs';
|
||||
|
||||
import type {
|
||||
@ -72,6 +73,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||
await updateProductFeatures(productId, { features });
|
||||
message.success('保存成功');
|
||||
emit('success');
|
||||
modalApi.close(); // 保存成功后关闭Modal
|
||||
return true;
|
||||
} catch {
|
||||
message.error('保存失败');
|
||||
@ -84,19 +86,15 @@ const loading = ref(false);
|
||||
const tempFeatureList = ref<TempFeatureItem[]>([]);
|
||||
|
||||
// 表格配置
|
||||
const [Grid, _gridApi] = useVbenVxeGrid({
|
||||
const [Grid] = useVbenVxeGrid({
|
||||
formOptions: {
|
||||
schema: useGridFormSchema(),
|
||||
submitOnChange: true,
|
||||
showCollapseButton: false,
|
||||
},
|
||||
separator: false,
|
||||
gridOptions: {
|
||||
columns: (
|
||||
useColumns((e: OnActionClickParams<FeatureApi.FeatureItem>) => {
|
||||
if (e.code === 'add' && e.row) {
|
||||
handleAddFeature(e.row);
|
||||
}
|
||||
}) || []
|
||||
).map((col) => {
|
||||
columns: (useColumns(onActionClick) || []).map((col) => {
|
||||
if (col.field === 'operation' && col.cellRender) {
|
||||
return {
|
||||
...col,
|
||||
@ -105,13 +103,23 @@ const [Grid, _gridApi] = useVbenVxeGrid({
|
||||
options: [
|
||||
{
|
||||
code: 'add',
|
||||
title: '添加',
|
||||
text: '添加',
|
||||
show: (row: FeatureApi.FeatureItem) => {
|
||||
return !tempFeatureList.value.some(
|
||||
(item) => item.feature_id === row.id,
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
code: 'added',
|
||||
text: '已添加',
|
||||
disabled: true,
|
||||
show: (row: FeatureApi.FeatureItem) => {
|
||||
return tempFeatureList.value.some(
|
||||
(item) => item.feature_id === row.id,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
@ -120,6 +128,11 @@ const [Grid, _gridApi] = useVbenVxeGrid({
|
||||
}),
|
||||
height: 500,
|
||||
keepSource: true,
|
||||
pagerConfig: {
|
||||
pageSize: 8,
|
||||
pageSizes: [8, 20, 50, 100],
|
||||
pagerCount: 5,
|
||||
},
|
||||
proxyConfig: {
|
||||
ajax: {
|
||||
query: async ({ page }, formValues) => {
|
||||
@ -134,13 +147,6 @@ const [Grid, _gridApi] = useVbenVxeGrid({
|
||||
rowConfig: {
|
||||
keyField: 'id',
|
||||
},
|
||||
toolbarConfig: {
|
||||
custom: true,
|
||||
export: false,
|
||||
refresh: { code: 'query' },
|
||||
search: true,
|
||||
zoom: true,
|
||||
},
|
||||
} as VxeTableGridOptions<FeatureApi.FeatureItem>,
|
||||
});
|
||||
|
||||
@ -215,10 +221,22 @@ async function loadFeatureList() {
|
||||
try {
|
||||
const res = await getProductFeatureList(productId);
|
||||
// 转换为临时数据格式
|
||||
tempFeatureList.value = res.map((item) => ({
|
||||
let tempList = res.map((item) => ({
|
||||
...item,
|
||||
temp_id: `existing_${item.id}`,
|
||||
}));
|
||||
// 对sort字段进行排序,如果全为0则按原顺序赋递增sort
|
||||
const allSortZero = tempList.every((item) => !item.sort || item.sort === 0);
|
||||
if (allSortZero) {
|
||||
tempList.forEach((item, idx) => {
|
||||
item.sort = idx + 1;
|
||||
});
|
||||
} else {
|
||||
tempList = [...tempList]
|
||||
.sort((a, b) => (a.sort || 0) - (b.sort || 0))
|
||||
.map((item, idx) => ({ ...item, sort: idx + 1 }));
|
||||
}
|
||||
tempFeatureList.value = tempList;
|
||||
initSortable();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@ -234,7 +252,8 @@ async function initSortable() {
|
||||
animation: 150,
|
||||
handle: '.ant-table-row',
|
||||
onEnd: async (evt: SortableEvent) => {
|
||||
const { newIndex, oldIndex } = evt;
|
||||
let { newIndex, oldIndex } = evt;
|
||||
// 兼容性保护,如果为 undefined/null 则不处理
|
||||
if (
|
||||
typeof newIndex !== 'number' ||
|
||||
typeof oldIndex !== 'number' ||
|
||||
@ -242,6 +261,10 @@ async function initSortable() {
|
||||
)
|
||||
return;
|
||||
|
||||
// 1-based 转为 0-based
|
||||
newIndex = newIndex - 1;
|
||||
oldIndex = oldIndex - 1;
|
||||
|
||||
// 重新排序列表
|
||||
const newList = [...tempFeatureList.value];
|
||||
const [removed] = newList.splice(oldIndex, 1);
|
||||
@ -258,7 +281,15 @@ async function initSortable() {
|
||||
|
||||
await initializeSortable();
|
||||
}
|
||||
|
||||
// 操作处理函数
|
||||
function onActionClick(e: OnActionClickParams<FeatureApi.FeatureItem>) {
|
||||
switch (e.code) {
|
||||
case 'add': {
|
||||
handleAddFeature(e.row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理添加模块
|
||||
function handleAddFeature(feature: FeatureApi.FeatureItem) {
|
||||
// 获取当前最大排序值
|
||||
@ -299,20 +330,22 @@ function handleRemoveFeature(record: TempFeatureItem) {
|
||||
|
||||
<template>
|
||||
<Modal class="w-[calc(100vw-200px)]">
|
||||
<div class="p-4">
|
||||
<div class="mb-4 text-gray-500">
|
||||
提示:可以通过拖拽行来调整模块顺序,通过开关控制模块的启用状态和重要程度
|
||||
</div>
|
||||
<div class="px-2">
|
||||
<div class="flex gap-4">
|
||||
<!-- 左侧:可选模块列表 -->
|
||||
<div class="w-[600px] flex-shrink-0">
|
||||
<div class="mb-2 text-base font-medium">可选模块</div>
|
||||
<!-- <div class="mb-2 text-base font-medium">可选模块</div>
|
||||
<div class="mb-4 text-sm text-gray-500">
|
||||
提示:点击添加可以快速添加模块到已关联模块列表
|
||||
</div> -->
|
||||
<Grid />
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已关联模块列表 -->
|
||||
<div class="flex-1">
|
||||
<div class="mb-2 text-base font-medium">已关联模块</div>
|
||||
<div class="mb-4 text-sm text-gray-500">
|
||||
提示:可以通过拖拽行来调整模块顺序,通过开关控制模块的启用状态和重要程度
|
||||
</div>
|
||||
<Table
|
||||
:columns="columns"
|
||||
:data-source="tempFeatureList"
|
||||
@ -321,6 +354,7 @@ function handleRemoveFeature(record: TempFeatureItem) {
|
||||
:row-key="(record) => record.temp_id"
|
||||
:scroll="{ y: 500 }"
|
||||
class="sortable-table"
|
||||
size="small"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.dataIndex === 'sort'">
|
||||
|
File diff suppressed because one or more lines are too long
@ -56,6 +56,10 @@
|
||||
"update:deps": "npx taze -r -w",
|
||||
"version": "pnpm exec changeset version && pnpm install --no-frozen-lockfile"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/changelog-github": "catalog:",
|
||||
"@changesets/cli": "catalog:",
|
||||
@ -114,9 +118,5 @@
|
||||
"canvas",
|
||||
"node-gyp"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12"
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,5 @@ export const MdiGithub = createIconifyIcon('mdi:github');
|
||||
export const MdiGoogle = createIconifyIcon('mdi:google');
|
||||
|
||||
export const MdiQqchat = createIconifyIcon('mdi:qqchat');
|
||||
|
||||
export const MdiArrowLeft = createIconifyIcon('mdi:arrow-left');
|
||||
|
Loading…
Reference in New Issue
Block a user