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 (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
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled
181 lines
5.3 KiB
Vue
181 lines
5.3 KiB
Vue
<script lang="ts" setup>
|
||
import { ref } from 'vue';
|
||
|
||
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
|
||
|
||
import {
|
||
Avatar,
|
||
Button,
|
||
InputNumber,
|
||
message,
|
||
Popover,
|
||
Switch,
|
||
Tag,
|
||
} from 'ant-design-vue';
|
||
|
||
import { useCrudTable } from '#/components/crud';
|
||
import { TableAction } from '#/components/table-action';
|
||
|
||
import { setAgent, setPriceNumber, setShowPrice, wxUserApi } from './api';
|
||
import WxUserBindModal from './components/bind-modal.vue';
|
||
import WxUserChildrenDrawer from './components/children-drawer.vue';
|
||
import WxUserFormModal from './components/modal.vue';
|
||
import { formOptions } from './config/search';
|
||
import { gridOptions } from './config/table';
|
||
|
||
const { FormModal, Grid, gridApi, showModal } = useCrudTable({
|
||
api: wxUserApi,
|
||
formOptions,
|
||
gridOptions,
|
||
modalComponent: WxUserFormModal,
|
||
toFormValues: (row) => ({
|
||
id: row.id,
|
||
nick_name: row.nick_name,
|
||
phone: row.phone,
|
||
price_number: row.price_number ?? '1',
|
||
show_price: row.show_price ?? 0,
|
||
}),
|
||
});
|
||
|
||
const [BindModal, bindModalApi] = useVbenModal({
|
||
connectedComponent: WxUserBindModal,
|
||
});
|
||
|
||
const [ChildrenDrawer, childrenDrawerApi] = useVbenDrawer({
|
||
connectedComponent: WxUserChildrenDrawer,
|
||
});
|
||
|
||
/** 倍率气泡里的临时值,按行 id 存,避免多行互相覆盖 */
|
||
const multiplierDraft = ref<Record<number, number>>({});
|
||
|
||
function openBind(row: Record<string, any>) {
|
||
bindModalApi.setData({ gridApi, record: row });
|
||
bindModalApi.open();
|
||
}
|
||
|
||
function openChildren(row: Record<string, any>) {
|
||
childrenDrawerApi.setData({ record: row });
|
||
childrenDrawerApi.open();
|
||
}
|
||
|
||
async function toggleAgent(row: Record<string, any>, checked: boolean) {
|
||
await setAgent({ id: row.id, is_p: checked ? 1 : 0 });
|
||
message.success(checked ? '已认定为代理商' : '已取消代理商');
|
||
gridApi.reload();
|
||
}
|
||
|
||
async function toggleShowPrice(row: Record<string, any>, checked: boolean) {
|
||
await setShowPrice({ id: row.id, show_price: checked ? 1 : 0 });
|
||
message.success('操作成功');
|
||
gridApi.reload();
|
||
}
|
||
|
||
async function saveMultiplier(row: Record<string, any>) {
|
||
const value = multiplierDraft.value[row.id] ?? Number(row.price_number ?? 1);
|
||
if (!value || value <= 0) {
|
||
message.warning('倍率必须大于 0');
|
||
return;
|
||
}
|
||
await setPriceNumber({ id: row.id, number: String(value) });
|
||
message.success('倍率已更新,价格已对该用户可见');
|
||
gridApi.reload();
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<Page auto-content-height title="微信用户">
|
||
<FormModal />
|
||
<BindModal />
|
||
<ChildrenDrawer />
|
||
<Grid>
|
||
<template #toolbar-actions>
|
||
<span class="text-xs text-muted-foreground">
|
||
微信用户由小程序授权登录产生,后台不支持新建。
|
||
</span>
|
||
</template>
|
||
<template #avatar="{ row }">
|
||
<Avatar :size="32" :src="row.avatar">
|
||
{{ (row.nick_name ?? '').slice(0, 1) }}
|
||
</Avatar>
|
||
</template>
|
||
<template #enterprise="{ row }">
|
||
<Button size="small" type="link" @click="openBind(row)">
|
||
{{ row.enterprise_name || '未绑定' }}
|
||
</Button>
|
||
</template>
|
||
<template #agent="{ row }">
|
||
<Switch
|
||
:checked="row.is_p === 1"
|
||
checked-children="代理"
|
||
un-checked-children="普通"
|
||
@change="(checked: any) => toggleAgent(row, !!checked)"
|
||
/>
|
||
</template>
|
||
<template #showPrice="{ row }">
|
||
<Switch
|
||
:checked="row.show_price === 1"
|
||
checked-children="可见"
|
||
un-checked-children="隐藏"
|
||
@change="(checked: any) => toggleShowPrice(row, !!checked)"
|
||
/>
|
||
</template>
|
||
<template #multiplier="{ row }">
|
||
<Popover trigger="click">
|
||
<template #content>
|
||
<div class="flex items-center gap-2">
|
||
<InputNumber
|
||
:min="0.01"
|
||
:precision="2"
|
||
:step="0.1"
|
||
:value="
|
||
multiplierDraft[row.id] ?? Number(row.price_number ?? 1)
|
||
"
|
||
@update:value="
|
||
(val: any) => (multiplierDraft[row.id] = Number(val))
|
||
"
|
||
/>
|
||
<Button size="small" type="primary" @click="saveMultiplier(row)">
|
||
保存
|
||
</Button>
|
||
</div>
|
||
<p class="mt-1 text-xs text-muted-foreground">
|
||
保存后该用户价格即为「原价 × 倍率」,并自动开启价格可见。
|
||
</p>
|
||
</template>
|
||
<Tag class="cursor-pointer" color="blue">
|
||
x{{ row.price_number || '1' }}
|
||
</Tag>
|
||
</Popover>
|
||
</template>
|
||
<template #action="{ row }">
|
||
<TableAction
|
||
:actions="[
|
||
{
|
||
label: '编辑',
|
||
type: 'link',
|
||
icon: 'uil:edit',
|
||
size: 'small',
|
||
onClick: () => showModal(row, true),
|
||
},
|
||
{
|
||
label: '绑定企业',
|
||
type: 'link',
|
||
icon: 'lucide:building',
|
||
size: 'small',
|
||
onClick: () => openBind(row),
|
||
},
|
||
{
|
||
label: '下级',
|
||
type: 'link',
|
||
icon: 'lucide:users',
|
||
size: 'small',
|
||
ifShow: row.is_p === 1,
|
||
onClick: () => openChildren(row),
|
||
},
|
||
]"
|
||
/>
|
||
</template>
|
||
</Grid>
|
||
</Page>
|
||
</template>
|