add entrance transition
This commit is contained in:
@@ -25,40 +25,45 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<customer-profile-card class="customer" :customer="selectedCustomer" />
|
||||
<customer-profile-card v-entrance-transition class="customer" :customer="selectedCustomer" />
|
||||
<div class="charts">
|
||||
<customer-chart-summary
|
||||
v-if="selectedCustomer"
|
||||
:customer="selectedCustomer"
|
||||
:month-cursor="monthCursor"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-event-record-calendar-section
|
||||
v-if="selectedCustomer"
|
||||
v-model="monthCursor"
|
||||
v-model:selected-event-id-list="selectedEventIdList"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:customer-name="selectedCustomer.name"
|
||||
:store-id="selectedCustomer.storeId"
|
||||
@list="toEventRecordList"
|
||||
/>
|
||||
<customer-record-trend-chart
|
||||
v-if="selectedCustomer"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:date-text-list="chartDateTextList"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-event-structure-chart
|
||||
v-if="selectedCustomer"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:date-text-list="monthDateTextList"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-selector
|
||||
v-model="selectedCustomerId"
|
||||
v-model:visible="selectorVisible"
|
||||
@change="handleCustomerSelected"
|
||||
/>
|
||||
<customer-chart-summary
|
||||
v-entrance-transition="70"
|
||||
v-if="selectedCustomer"
|
||||
:customer="selectedCustomer"
|
||||
:month-cursor="monthCursor"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-event-record-calendar-section
|
||||
v-entrance-transition="140"
|
||||
v-if="selectedCustomer"
|
||||
v-model="monthCursor"
|
||||
v-model:selected-event-id-list="selectedEventIdList"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:customer-name="selectedCustomer.name"
|
||||
:store-id="selectedCustomer.storeId"
|
||||
@list="toEventRecordList"
|
||||
/>
|
||||
<customer-record-trend-chart
|
||||
v-entrance-transition="210"
|
||||
v-if="selectedCustomer"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:date-text-list="chartDateTextList"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-event-structure-chart
|
||||
v-entrance-transition="280"
|
||||
v-if="selectedCustomer"
|
||||
:customer-id="selectedCustomer.id || ''"
|
||||
:date-text-list="monthDateTextList"
|
||||
:selected-event-id-list="selectedEventIdList"
|
||||
/>
|
||||
<customer-selector
|
||||
v-entrance-transition="350"
|
||||
v-model="selectedCustomerId"
|
||||
v-model:visible="selectorVisible"
|
||||
@change="handleCustomerSelected"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.customer.read" class="customer-detail">
|
||||
<customer-profile-card
|
||||
v-entrance-transition
|
||||
class="customer"
|
||||
:customer="customer"
|
||||
/>
|
||||
<t-cell-group v-if="customer" class="info" theme="card">
|
||||
<t-cell-group v-entrance-transition="70" v-if="customer" class="info" theme="card">
|
||||
<t-cell title="出生日期">
|
||||
<span
|
||||
v-if="isLunarBirthdate"
|
||||
@@ -43,9 +44,10 @@
|
||||
v-if="customer && canReadTag"
|
||||
:editable="canApplyTag"
|
||||
:tag-list="customerTagList"
|
||||
v-entrance-transition="140"
|
||||
@edit="openTagSelector"
|
||||
/>
|
||||
<t-cell-group v-if="customer" theme="card">
|
||||
<t-cell-group v-if="customer" theme="card" v-entrance-transition="210">
|
||||
<t-cell v-if="canReadStat" title="客户数据图表" arrow @click="toCustomerDataCharts">
|
||||
<template #left-icon>
|
||||
<t-icon name="chart" />
|
||||
@@ -63,13 +65,19 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-if="inviter" :title="`由 ${inviter.name} 邀请`" theme="card">
|
||||
<t-cell-group
|
||||
v-if="inviter"
|
||||
:title="`由 ${inviter.name} 邀请`"
|
||||
theme="card"
|
||||
v-entrance-transition="280"
|
||||
>
|
||||
<customer-profile-card :customer="inviter" @click="toCustomerDetail(inviter)"/>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-if="customer" theme="card">
|
||||
<t-cell title="邀请客户" :note="inviteeCountText" arrow @click="toInviteeList" />
|
||||
</t-cell-group>
|
||||
<t-button
|
||||
v-if="customer"
|
||||
v-can="permissionCodes.customer.delete"
|
||||
class="delete-action"
|
||||
theme="danger"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="savePermissionCode" class="customer-edit">
|
||||
<t-form class="form" label-align="left" label-width="6rem">
|
||||
<t-form class="form" label-align="left" label-width="6rem" v-entrance-transition>
|
||||
<t-form-item label="客户编码">
|
||||
<t-input
|
||||
v-model.trim="formData.code"
|
||||
@@ -112,9 +112,10 @@
|
||||
class="tag-card"
|
||||
:editable="canEditTag"
|
||||
:tag-list="customerTagList"
|
||||
v-entrance-transition="70"
|
||||
@edit="openTagSelector"
|
||||
/>
|
||||
<t-form class="form" label-align="left" label-width="3rem">
|
||||
<t-form class="form" label-align="left" label-width="3rem" v-entrance-transition="140">
|
||||
<t-form-item label="住址">
|
||||
<t-textarea
|
||||
class="textarea"
|
||||
@@ -162,7 +163,7 @@
|
||||
<bottom-popup
|
||||
v-model="bodyAreaPickerVisible"
|
||||
title="选择调理部位"
|
||||
height="38rem"
|
||||
height="32rem"
|
||||
@left-button-click="cancelBodyAreaPicker"
|
||||
@right-button-click="confirmBodyAreaPicker"
|
||||
>
|
||||
|
||||
@@ -38,18 +38,19 @@
|
||||
@scrolltolower="fetch"
|
||||
>
|
||||
<t-cell-group class="items" theme="card">
|
||||
<customer-cell
|
||||
class="item"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id || item.code || index"
|
||||
:customer="item"
|
||||
arrow
|
||||
@click="router.push(`/management/customers/${item.id}`)"
|
||||
>
|
||||
<template #description>
|
||||
<telephone-link :value="item.telephone" />
|
||||
</template>
|
||||
</customer-cell>
|
||||
<customer-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id || item.code || index"
|
||||
class="item"
|
||||
:customer="item"
|
||||
arrow
|
||||
@click="router.push(`/management/customers/${item.id}`)"
|
||||
>
|
||||
<template #description>
|
||||
<telephone-link :value="item.telephone" />
|
||||
</template>
|
||||
</customer-cell>
|
||||
</t-cell-group>
|
||||
<div v-if="!pageResult.list.length" class="load-state" v-text="isLoading ? '正在加载客户' : '暂无客户数据'" />
|
||||
<div v-if="pageResult.list.length" class="load-state" v-text="isLoading ? '正在加载更多' : isNoMore ? '已经到底了' : '上拉加载更多'" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.qrCode.create" class="qr-page">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form class="form" label-align="left" v-entrance-transition>
|
||||
<t-form-item label="编码前缀">
|
||||
<t-input v-model.trim="formModel.prefix" placeholder="如 GAO" borderless />
|
||||
</t-form-item>
|
||||
@@ -32,11 +32,11 @@
|
||||
/>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-cell-group theme="card">
|
||||
<t-cell-group theme="card" v-entrance-transition="70">
|
||||
<t-cell title="最终起始编码" :note="finalStartCode" />
|
||||
<t-cell title="最终结束编码" :note="finalEndCode" />
|
||||
</t-cell-group>
|
||||
<div class="actions">
|
||||
<div class="actions" v-entrance-transition="140">
|
||||
<t-button
|
||||
class="bg-white"
|
||||
theme="primary"
|
||||
@@ -54,8 +54,8 @@
|
||||
<span v-text="downloadText" />
|
||||
</t-button>
|
||||
</div>
|
||||
<div class="actions orange tips">微信内可能无法发起打印或批量下载,建议使用默认浏览器打开</div>
|
||||
<section class="preview">
|
||||
<div class="actions orange tips" v-entrance-transition="140">微信内可能无法发起打印或批量下载,建议使用默认浏览器打开</div>
|
||||
<section class="preview" v-entrance-transition="210">
|
||||
<div class="header">
|
||||
<h2 class="title">预览</h2>
|
||||
<p class="tips" v-text="previewSummary" />
|
||||
|
||||
@@ -3,59 +3,55 @@
|
||||
v-can="permissionCodes.event.read"
|
||||
class="registration-event-detail"
|
||||
>
|
||||
<section v-if="event" class="event-header">
|
||||
<div class="color" :style="{ background: event.color || defaultColor }" />
|
||||
<div class="header-content">
|
||||
<div class="title-row">
|
||||
<h2 v-text="event.name || '未命名事件'" />
|
||||
<t-tag :theme="getStatusTheme(event.status)" variant="light-outline" :content="getStatusText(event.status)" />
|
||||
<div v-entrance-transition v-if="event" class="event-header">
|
||||
<div class="color" :style="{ background: event.color || defaultColor }" />
|
||||
<div class="header-content">
|
||||
<div class="title-row">
|
||||
<h2 v-text="event.name || '未命名事件'" />
|
||||
<t-tag :theme="getStatusTheme(event.status)" variant="light-outline" :content="getStatusText(event.status)" />
|
||||
</div>
|
||||
<div class="description" v-text="Text.display(event.description)" />
|
||||
</div>
|
||||
<div class="description" v-text="Text.display(event.description)" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<t-cell-group v-if="event" title="基本信息" theme="card">
|
||||
<t-cell title="所属门店" :note="storeName" />
|
||||
<t-cell title="事件颜色">
|
||||
<template #note>
|
||||
<div class="color-note">
|
||||
<span class="color-dot" :style="{ background: event.color || defaultColor }" />
|
||||
<span v-text="(event.color || defaultColor).toLowerCase()" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell title="说明" :note="Text.display(event.description)" />
|
||||
<t-cell title="可登记角色">
|
||||
<template #note>
|
||||
<div v-if="event.roleCodeList?.length" class="tag-list">
|
||||
<t-tag
|
||||
v-for="roleCode in event.roleCodeList"
|
||||
:key="roleCode"
|
||||
theme="primary"
|
||||
variant="light-outline"
|
||||
:content="getRoleName(roleCode)"
|
||||
/>
|
||||
</div>
|
||||
<span v-else>未配置</span>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="event" title="登记配置" theme="card">
|
||||
<t-cell title="数值类型" :note="getValueTypeText(event.valueType)" />
|
||||
<t-cell v-if="event.valueType === 'NUMBER'" title="数值单位" :note="getValueUnitText(event.valueUnit)" />
|
||||
<t-cell v-if="event.valueType === 'NUMBER'" title="登记必填数值" :note="event.requireValue ? '是' : '否'" />
|
||||
<t-cell title="需要拍照" :note="event.requirePhoto ? '是' : '否'" />
|
||||
<t-cell title="次数约束" :note="getLimitText(event)" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="event" title="生效时间" theme="card">
|
||||
<t-cell title="起始时间" :note="formatDate(event.beginAt)" />
|
||||
<t-cell title="终止时间" :note="formatDate(event.endAt)" />
|
||||
<t-cell title="创建时间" :note="formatDate(event.createdAt, '未知时间')" />
|
||||
<t-cell title="更新时间" :note="formatDate(event.updatedAt, '未知时间')" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-entrance-transition="70" v-if="event" title="基本信息" theme="card">
|
||||
<t-cell title="所属门店" :note="storeName" />
|
||||
<t-cell title="事件颜色">
|
||||
<template #note>
|
||||
<div class="color-note">
|
||||
<span class="color-dot" :style="{ background: event.color || defaultColor }" />
|
||||
<span v-text="(event.color || defaultColor).toLowerCase()" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell title="说明" :note="Text.display(event.description)" />
|
||||
<t-cell title="可登记角色">
|
||||
<template #note>
|
||||
<div v-if="event.roleCodeList?.length" class="tag-list">
|
||||
<t-tag
|
||||
v-for="roleCode in event.roleCodeList"
|
||||
:key="roleCode"
|
||||
theme="primary"
|
||||
variant="light-outline"
|
||||
:content="getRoleName(roleCode)"
|
||||
/>
|
||||
</div>
|
||||
<span v-else>未配置</span>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-entrance-transition="140" v-if="event" title="登记配置" theme="card">
|
||||
<t-cell title="数值类型" :note="getValueTypeText(event.valueType)" />
|
||||
<t-cell v-if="event.valueType === 'NUMBER'" title="数值单位" :note="getValueUnitText(event.valueUnit)" />
|
||||
<t-cell v-if="event.valueType === 'NUMBER'" title="登记必填数值" :note="event.requireValue ? '是' : '否'" />
|
||||
<t-cell title="需要拍照" :note="event.requirePhoto ? '是' : '否'" />
|
||||
<t-cell title="次数约束" :note="getLimitText(event)" />
|
||||
</t-cell-group>
|
||||
<t-cell-group v-entrance-transition="210" v-if="event" title="生效时间" theme="card">
|
||||
<t-cell title="起始时间" :note="formatDate(event.beginAt)" />
|
||||
<t-cell title="终止时间" :note="formatDate(event.endAt)" />
|
||||
<t-cell title="创建时间" :note="formatDate(event.createdAt, '未知时间')" />
|
||||
<t-cell title="更新时间" :note="formatDate(event.updatedAt, '未知时间')" />
|
||||
</t-cell-group>
|
||||
<t-empty v-else :description="isLoading ? '正在加载登记事件' : '登记事件不存在'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="pageAccess" class="registration-event-edit">
|
||||
<t-form class="form" label-align="left" label-width="7rem">
|
||||
<t-form class="form" label-align="left" label-width="7rem" v-entrance-transition>
|
||||
<t-form-item label="颜色">
|
||||
<t-button
|
||||
size="extra-small"
|
||||
@@ -83,7 +83,7 @@
|
||||
<div class="picker-text" v-text="getStatusText(formModel.status)" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<section class="roles">
|
||||
<section class="roles" v-entrance-transition="70">
|
||||
<div class="title">
|
||||
<span>可登记角色</span>
|
||||
<span class="hint">必须至少选择一个角色,上级角色拥有子级角色可登记事件的登记权限</span>
|
||||
|
||||
@@ -10,45 +10,46 @@
|
||||
@scrolltolower="fetch"
|
||||
>
|
||||
<t-cell-group theme="card">
|
||||
<t-cell
|
||||
class="item"
|
||||
v-for="item in visibleEventList"
|
||||
:key="item.id"
|
||||
:arrow="!!item.id"
|
||||
:hover="!!item.id"
|
||||
@click="toEventItem(item)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<div class="color" :style="{ background: item.color || defaultColor }" />
|
||||
<div class="title" v-text="item.name || '未命名事件'" />
|
||||
<t-tag
|
||||
class="status"
|
||||
:theme="getStatusTag(item).theme"
|
||||
variant="outline"
|
||||
:content="getStatusTag(item).text"
|
||||
/>
|
||||
<t-tag v-if="item.requirePhoto" theme="warning" variant="outline">需拍照</t-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<div class="line">
|
||||
<span>可登记角色</span>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in visibleEventList"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:arrow="!!item.id"
|
||||
:hover="!!item.id"
|
||||
@click="toEventItem(item)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<div class="color" :style="{ background: item.color || defaultColor }" />
|
||||
<div class="title" v-text="item.name || '未命名事件'" />
|
||||
<t-tag
|
||||
v-for="roleCode in item.roleCodeList"
|
||||
:key="roleCode"
|
||||
theme="primary"
|
||||
variant="light-outline"
|
||||
:content="getRoleName(roleCode)"
|
||||
class="status"
|
||||
:theme="getStatusTag(item).theme"
|
||||
variant="outline"
|
||||
:content="getStatusTag(item).text"
|
||||
/>
|
||||
<span v-if="!(item.roleCodeList || []).length" class="muted" v-text="'未配置'" />
|
||||
<t-tag v-if="item.requirePhoto" theme="warning" variant="outline">需拍照</t-tag>
|
||||
</div>
|
||||
<div class="line" v-text="getLimitText(item)" />
|
||||
<div class="line" v-text="getValueDefinitionText(item)" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<div class="line">
|
||||
<span>可登记角色</span>
|
||||
<t-tag
|
||||
v-for="roleCode in item.roleCodeList"
|
||||
:key="roleCode"
|
||||
theme="primary"
|
||||
variant="light-outline"
|
||||
:content="getRoleName(roleCode)"
|
||||
/>
|
||||
<span v-if="!(item.roleCodeList || []).length" class="muted" v-text="'未配置'" />
|
||||
</div>
|
||||
<div class="line" v-text="getLimitText(item)" />
|
||||
<div class="line" v-text="getValueDefinitionText(item)" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<div v-if="!visibleEventList.length" class="empty-block" v-text="emptyText" />
|
||||
<div v-if="visibleEventList.length" class="load-state" v-text="isNoMore ? '已经到底了' : '上拉加载更多'" />
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.eventRecord.read" class="registration-record-detail">
|
||||
<customer-profile-card
|
||||
v-entrance-transition
|
||||
v-if="record?.customer"
|
||||
class="customer-profile"
|
||||
:customer="record.customer"
|
||||
@click="toCustomerDetail"
|
||||
/>
|
||||
<t-cell-group v-if="record" title="登记信息" theme="card">
|
||||
<t-cell-group v-entrance-transition="70" v-if="record" title="登记信息" theme="card">
|
||||
<t-cell title="登记事件" :note="record.event?.name || '未知事件'" />
|
||||
<t-cell v-if="record.numberValue !== undefined && record.numberValue !== null" title="事件数值" :note="getNumberValueText(record)" />
|
||||
<t-cell v-if="record.pointValue !== undefined && record.pointValue !== null" title="提交积分值" :note="getPointValueText(record.pointValue)" />
|
||||
@@ -16,15 +17,16 @@
|
||||
<t-cell title="客户编码" :note="Text.display(record.customer?.code)" />
|
||||
<t-cell title="备注" :note="Text.display(record.remark)" />
|
||||
</t-cell-group>
|
||||
<section v-if="record" class="photo-panel">
|
||||
<photo-scroller
|
||||
:model-value="recordPhotoList"
|
||||
:photo-items="recordPhotoItemList"
|
||||
:show-add="false"
|
||||
:show-remove="false"
|
||||
title="登记照片"
|
||||
/>
|
||||
</section>
|
||||
<photo-scroller
|
||||
v-entrance-transition="140"
|
||||
v-if="record"
|
||||
class="photo-panel"
|
||||
:model-value="recordPhotoList"
|
||||
:photo-items="recordPhotoItemList"
|
||||
:show-add="false"
|
||||
:show-remove="false"
|
||||
title="登记照片"
|
||||
/>
|
||||
<t-empty v-else :description="isLoading ? '正在加载登记事件记录' : '登记事件记录不存在'" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -141,8 +143,9 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
.photo-panel {
|
||||
padding: 1rem;
|
||||
width: calc(100% - 2rem);
|
||||
margin: 0 1rem;
|
||||
padding: 1rem;
|
||||
background: rgba(255, 255, 255, .92);
|
||||
box-shadow: var(--td-shadow-1);
|
||||
border-radius: 1.4rem;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="pageAccess" class="registration-record-edit">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form class="form" label-align="left" v-entrance-transition>
|
||||
<t-form-item label="客户" required-mark>
|
||||
<t-input
|
||||
:model-value="customerDisplayText"
|
||||
@@ -42,10 +42,11 @@
|
||||
v-if="showSelectedCustomerProfile"
|
||||
class="customer-profile"
|
||||
:customer="selectedCustomer"
|
||||
v-entrance-transition
|
||||
/>
|
||||
<event-selector
|
||||
v-model="selectedEventIdList"
|
||||
class="registration-event-selector"
|
||||
class="event-selector"
|
||||
:event-list="eventList"
|
||||
:disabled="isEditMode"
|
||||
required-mark
|
||||
@@ -804,7 +805,7 @@ watch(customerCode, async (value) => {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.registration-event-selector {
|
||||
.event-selector {
|
||||
padding: 0 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@@ -33,64 +33,65 @@
|
||||
@scrolltolower="loadRecords"
|
||||
>
|
||||
<div class="list-wrapper">
|
||||
<t-cell-group class="summary" theme="card">
|
||||
<t-cell
|
||||
title="开始时间"
|
||||
:note="dateRange[0] || '-'"
|
||||
arrow
|
||||
@click="startVisible = true"
|
||||
/>
|
||||
<t-cell
|
||||
title="结束时间"
|
||||
:note="dateRange[1] || '-'"
|
||||
arrow
|
||||
@click="endVisible = true"
|
||||
/>
|
||||
<t-cell title="事件" :note="eventFilterLabel" />
|
||||
<t-cell title="数据量" :note="summaryTotalText" />
|
||||
<t-cell v-if="summaryNumberValueText" title="数值合计" :note="summaryNumberValueText" />
|
||||
</t-cell-group>
|
||||
<t-cell-group v-entrance-transition class="summary" theme="card">
|
||||
<t-cell
|
||||
title="开始时间"
|
||||
:note="dateRange[0] || '-'"
|
||||
arrow
|
||||
@click="startVisible = true"
|
||||
/>
|
||||
<t-cell
|
||||
title="结束时间"
|
||||
:note="dateRange[1] || '-'"
|
||||
arrow
|
||||
@click="endVisible = true"
|
||||
/>
|
||||
<t-cell title="事件" :note="eventFilterLabel" />
|
||||
<t-cell title="数据量" :note="summaryTotalText" />
|
||||
<t-cell v-if="summaryNumberValueText" title="数值合计" :note="summaryNumberValueText" />
|
||||
</t-cell-group>
|
||||
<t-cell-group
|
||||
v-if="pageResult.list.length"
|
||||
class="record-list"
|
||||
theme="card"
|
||||
>
|
||||
<t-swipe-cell
|
||||
v-for="item in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<t-cell
|
||||
class="cell"
|
||||
:title="getRecordEventName(item)"
|
||||
:description="getRecordCustomerName(item)"
|
||||
:note="getRecordRegisteredAt(item)"
|
||||
arrow
|
||||
hover
|
||||
@click="toDetail(item.id || '')"
|
||||
<t-swipe-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-image
|
||||
v-if="getRecordPhotoURL(item)"
|
||||
:src="getRecordPhotoURL(item)"
|
||||
:alt="getRecordEventName(item)"
|
||||
fit="cover"
|
||||
class="avatar"
|
||||
/>
|
||||
<div v-else class="avatar fallback" v-text="getRecordCustomerInitial(item)" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<template v-if="canDeleteRecord" #right>
|
||||
<t-button
|
||||
class="delete"
|
||||
theme="danger"
|
||||
:loading="isDeleting && deletingId === item.id"
|
||||
@click.stop="confirmRemoveRecord(item)"
|
||||
<t-cell
|
||||
class="cell"
|
||||
:title="getRecordEventName(item)"
|
||||
:description="getRecordCustomerName(item)"
|
||||
:note="getRecordRegisteredAt(item)"
|
||||
arrow
|
||||
hover
|
||||
@click="toDetail(item.id || '')"
|
||||
>
|
||||
删除
|
||||
</t-button>
|
||||
</template>
|
||||
</t-swipe-cell>
|
||||
<template #leftIcon>
|
||||
<t-image
|
||||
v-if="getRecordPhotoURL(item)"
|
||||
:src="getRecordPhotoURL(item)"
|
||||
:alt="getRecordEventName(item)"
|
||||
fit="cover"
|
||||
class="avatar"
|
||||
/>
|
||||
<div v-else class="avatar fallback" v-text="getRecordCustomerInitial(item)" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<template v-if="canDeleteRecord" #right>
|
||||
<t-button
|
||||
class="delete"
|
||||
theme="danger"
|
||||
:loading="isDeleting && deletingId === item.id"
|
||||
@click.stop="confirmRemoveRecord(item)"
|
||||
>
|
||||
删除
|
||||
</t-button>
|
||||
</template>
|
||||
</t-swipe-cell>
|
||||
</t-cell-group>
|
||||
<div v-else class="load-state" v-text="isLoading ? '正在加载登记事件记录' : '暂无登记事件记录'" />
|
||||
<div v-if="pageResult.list.length" class="load-state" v-text="loadStateText" />
|
||||
|
||||
@@ -47,55 +47,56 @@
|
||||
class="list"
|
||||
theme="card"
|
||||
>
|
||||
<customer-cell
|
||||
class="item"
|
||||
:class="{ 'in-top3': index < 3}"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.customerId"
|
||||
arrow
|
||||
@click="toCustomerDetail(item.customerId || '')"
|
||||
:customer="item.customer"
|
||||
>
|
||||
<template #note>
|
||||
<div
|
||||
class="rank"
|
||||
:class="{
|
||||
<customer-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.customerId"
|
||||
class="item"
|
||||
:class="{ 'in-top3': index < 3}"
|
||||
arrow
|
||||
@click="toCustomerDetail(item.customerId || '')"
|
||||
:customer="item.customer"
|
||||
>
|
||||
<template #note>
|
||||
<div
|
||||
class="rank"
|
||||
:class="{
|
||||
top1: index === 0,
|
||||
top2: index === 1,
|
||||
top3: index === 2,
|
||||
}"
|
||||
v-text="index + 1"
|
||||
/>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<t-tag
|
||||
v-if="rankType === 'TOTAL_DAYS'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`累计天数 ${item.totalEventDays || 0}`"
|
||||
v-text="index + 1"
|
||||
/>
|
||||
<t-tag
|
||||
v-else-if="rankType === 'TOTAL_COUNT'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`累计次数 ${item.totalEventCount || 0}`"
|
||||
/>
|
||||
<t-tag
|
||||
v-else-if="rankType === 'CONTINUOUS_DAYS'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`连续天数 ${item.recentContinuousEventDays || 0}`"
|
||||
/>
|
||||
<t-tag
|
||||
v-else
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`登记数值 ${getTotalNumberValueText(item)}`"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</customer-cell>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<t-tag
|
||||
v-if="rankType === 'TOTAL_DAYS'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`累计天数 ${item.totalEventDays || 0}`"
|
||||
/>
|
||||
<t-tag
|
||||
v-else-if="rankType === 'TOTAL_COUNT'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`累计次数 ${item.totalEventCount || 0}`"
|
||||
/>
|
||||
<t-tag
|
||||
v-else-if="rankType === 'CONTINUOUS_DAYS'"
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`连续天数 ${item.recentContinuousEventDays || 0}`"
|
||||
/>
|
||||
<t-tag
|
||||
v-else
|
||||
size="small"
|
||||
variant="outline"
|
||||
:content="`登记数值 ${getTotalNumberValueText(item)}`"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</customer-cell>
|
||||
</t-cell-group>
|
||||
<div v-else class="load-state" v-text="emptyStateText" />
|
||||
<div v-if="pageResult.list.length" class="load-state" v-text="loadStateText" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.event.update" class="registration-event-sort">
|
||||
<div class="tip" v-text="'按住右侧拖动手柄调整事件顺序,保存后生效'" />
|
||||
<div class="tip" v-text="'按住右侧拖动手柄调整事件顺序,保存后生效'" v-entrance-transition />
|
||||
<div class="items">
|
||||
<t-cell-group v-if="eventList.length" theme="card">
|
||||
<vue-draggable-next
|
||||
@@ -16,10 +16,11 @@
|
||||
@change="handleSortChange"
|
||||
>
|
||||
<t-cell
|
||||
v-for="element in eventList"
|
||||
v-for="(element, index) in eventList"
|
||||
:key="element.id"
|
||||
class="cell"
|
||||
:title="element.name || '未命名事件'"
|
||||
v-entrance-transition="index * 30"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<div class="color" :style="{ background: element.color || defaultColor }" />
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<t-form-item label-width="0">
|
||||
<event-selector
|
||||
v-model="selectedEventIdList"
|
||||
class="registration-event-selector"
|
||||
class="event-selector"
|
||||
:event-list="eventList"
|
||||
/>
|
||||
</t-form-item>
|
||||
@@ -846,7 +846,7 @@ watch(scanCode, (value) => {
|
||||
box-shadow: 0 .75rem 2rem rgba(2, 6, 23, .32);
|
||||
}
|
||||
|
||||
.registration-event-selector {
|
||||
.event-selector {
|
||||
|
||||
:deep(.item) {
|
||||
color: #e2e8f0;
|
||||
|
||||
@@ -7,24 +7,25 @@
|
||||
@refresh="refresh"
|
||||
>
|
||||
<div class="content">
|
||||
<t-cell-group class="header" theme="card">
|
||||
<t-cell title="当前账号角色聚合权限 P">
|
||||
<template #description>
|
||||
<div>你拥有以下权限,可执行权限对应的功能,这些权限来自上级角色直接授权或子角色继承。</div>
|
||||
<permission-legend />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-entrance-transition class="header" theme="card">
|
||||
<t-cell title="当前账号角色聚合权限 P">
|
||||
<template #description>
|
||||
<div>你拥有以下权限,可执行权限对应的功能,这些权限来自上级角色直接授权或子角色继承。</div>
|
||||
<permission-legend />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-if="sortedPermissions.length" theme="card">
|
||||
<t-swipe-cell
|
||||
v-for="item in sortedPermissions"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<permission-cell :permission="item" :source="item.source" />
|
||||
</t-swipe-cell>
|
||||
<t-swipe-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in sortedPermissions"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<permission-cell :permission="item" :source="item.source" />
|
||||
</t-swipe-cell>
|
||||
</t-cell-group>
|
||||
<t-empty v-else-if="!permissionStore.loading && !isSourceLoading" description="暂无权限" />
|
||||
<t-empty v-if="!permissionStore.loading && !isSourceLoading" description="暂无权限" />
|
||||
</div>
|
||||
</t-pull-down-refresh>
|
||||
</div>
|
||||
|
||||
@@ -57,20 +57,20 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group title="当前角色结构" theme="card">
|
||||
<t-cell
|
||||
v-can="{ value: [corePermissionCodes.role.read, corePermissionCodes.permission.read], mode: 'and' }"
|
||||
v-for="item in visibleRoleTree"
|
||||
:key="item.id"
|
||||
:arrow="canAssignRole(item)"
|
||||
:hover="canAssignRole(item)"
|
||||
@click="canAssignRole(item) && toAssign(item.id)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-text="item.name" :style="{ paddingLeft: `${item.level * 1.25}rem` }" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-entrance-transition title="当前角色结构" theme="card">
|
||||
<t-cell
|
||||
v-can="{ value: [corePermissionCodes.role.read, corePermissionCodes.permission.read], mode: 'and' }"
|
||||
v-for="item in visibleRoleTree"
|
||||
:key="item.id"
|
||||
:arrow="canAssignRole(item)"
|
||||
:hover="canAssignRole(item)"
|
||||
@click="canAssignRole(item) && toAssign(item.id)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-text="item.name" :style="{ paddingLeft: `${item.level * 1.25}rem` }" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -181,4 +181,3 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -19,22 +19,23 @@
|
||||
title="允许该角色可继续往下级角色转授权限"
|
||||
theme="card"
|
||||
>
|
||||
<t-cell
|
||||
v-for="item in grantablePermissionList"
|
||||
:key="item.id"
|
||||
:title="item.name || item.code"
|
||||
>
|
||||
<template #description>
|
||||
<span class="code" v-text="item.code"></span>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
:disabled="!canUpdateRolePermission || !canEditActiveRole"
|
||||
:model-value="isPermissionChecked(item.id)"
|
||||
@change="value => setPermissionChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in grantablePermissionList"
|
||||
:key="item.id"
|
||||
:title="item.name || item.code"
|
||||
>
|
||||
<template #description>
|
||||
<span class="code" v-text="item.code"></span>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
:disabled="!canUpdateRolePermission || !canEditActiveRole"
|
||||
:model-value="isPermissionChecked(item.id)"
|
||||
@change="value => setPermissionChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-empty v-else-if="!permissionStore.loading" description="暂无可配置的转授权限 D" />
|
||||
</div>
|
||||
|
||||
@@ -1,57 +1,56 @@
|
||||
<template>
|
||||
<div v-can="pageAccess" class="role-edit">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form-item label="名称">
|
||||
<t-input v-model.trim="formModel.name" placeholder="角色名称" borderless :disabled="!canEditRoleInfo" />
|
||||
</t-form-item>
|
||||
<t-form-item label="代码" :help="isBuiltinRole ? '内建角色代码不可修改' : ''">
|
||||
<t-input v-model.trim="formModel.code" placeholder="如 front-desk" borderless :disabled="!canEditRoleCode" />
|
||||
</t-form-item>
|
||||
<t-form-item label="模块">
|
||||
<t-input v-model.trim="formModel.moduleCode" placeholder="模块代码" borderless disabled />
|
||||
</t-form-item>
|
||||
<t-form-item
|
||||
label="上级"
|
||||
:arrow="canEditParentRole"
|
||||
@click.stop="openParentRolePicker"
|
||||
>
|
||||
<div class="picker-text" v-text="selectedParentRoleName" />
|
||||
</t-form-item>
|
||||
<t-form-item label="说明">
|
||||
<t-textarea v-model.trim="formModel.description" class="textarea" placeholder="角色说明" autosize borderless :disabled="!canEditRoleInfo" />
|
||||
</t-form-item>
|
||||
<t-form-item
|
||||
label="继承角色"
|
||||
:arrow="canEditRoleRelation"
|
||||
@click.stop="openChildRolePicker"
|
||||
>
|
||||
<div class="picker-text" v-text="selectedChildRoleName" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-cell-group v-if="!isCreateMode" title="权限授权" theme="card">
|
||||
<t-cell
|
||||
v-can="rolePermissionReadAccess"
|
||||
title="直接授权权限 P"
|
||||
arrow
|
||||
@click="toRolePermissionPage"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="secured" size="1.5rem" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-can="rolePermissionReadAccess"
|
||||
title="可转授权限 D"
|
||||
arrow
|
||||
@click="toRoleDelegationPage"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="user-checked" size="1.5rem" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<template v-if="aggregatePermissionList.length">
|
||||
<card-container title="聚合权限 P">
|
||||
<t-form v-entrance-transition class="form" label-align="left">
|
||||
<t-form-item label="名称">
|
||||
<t-input v-model.trim="formModel.name" placeholder="角色名称" borderless :disabled="!canEditRoleInfo" />
|
||||
</t-form-item>
|
||||
<t-form-item label="代码" :help="isBuiltinRole ? '内建角色代码不可修改' : ''">
|
||||
<t-input v-model.trim="formModel.code" placeholder="如 front-desk" borderless :disabled="!canEditRoleCode" />
|
||||
</t-form-item>
|
||||
<t-form-item label="模块">
|
||||
<t-input v-model.trim="formModel.moduleCode" placeholder="模块代码" borderless disabled />
|
||||
</t-form-item>
|
||||
<t-form-item
|
||||
label="上级"
|
||||
:arrow="canEditParentRole"
|
||||
@click.stop="openParentRolePicker"
|
||||
>
|
||||
<div class="picker-text" v-text="selectedParentRoleName" />
|
||||
</t-form-item>
|
||||
<t-form-item label="说明">
|
||||
<t-textarea v-model.trim="formModel.description" class="textarea" placeholder="角色说明" autosize borderless :disabled="!canEditRoleInfo" />
|
||||
</t-form-item>
|
||||
<t-form-item
|
||||
label="继承角色"
|
||||
:arrow="canEditRoleRelation"
|
||||
@click.stop="openChildRolePicker"
|
||||
>
|
||||
<div class="picker-text" v-text="selectedChildRoleName" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-cell-group v-entrance-transition="70" v-if="!isCreateMode" title="权限授权" theme="card">
|
||||
<t-cell
|
||||
v-can="rolePermissionReadAccess"
|
||||
title="直接授权权限 P"
|
||||
arrow
|
||||
@click="toRolePermissionPage"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="secured" size="1.5rem" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-can="rolePermissionReadAccess"
|
||||
title="可转授权限 D"
|
||||
arrow
|
||||
@click="toRoleDelegationPage"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="user-checked" size="1.5rem" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<card-container v-entrance-transition="140" v-if="aggregatePermissionList.length" title="聚合权限 P">
|
||||
<template #description>
|
||||
<div>该角色拥有以下权限,可执行权限对应的功能,这些权限来自上级角色直接授权或子角色继承。</div>
|
||||
<permission-legend />
|
||||
@@ -65,7 +64,6 @@
|
||||
/>
|
||||
</t-cell-group>
|
||||
</card-container>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<t-popup v-model="parentRolePickerVisible" placement="bottom">
|
||||
|
||||
@@ -7,26 +7,27 @@
|
||||
@refresh="refresh"
|
||||
>
|
||||
<t-cell-group v-if="sortedRoles.length" theme="card">
|
||||
<t-swipe-cell
|
||||
v-for="item in sortedRoles"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<t-cell
|
||||
:title="item.name"
|
||||
:note="item.code"
|
||||
arrow
|
||||
hover
|
||||
@click="router.push(`/management/permissions/roles/${item.id}`)"
|
||||
<t-swipe-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in sortedRoles"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-text="item.name" :style="{ paddingLeft: `${item.level * 1.25}rem` }" />
|
||||
<t-cell
|
||||
:title="item.name"
|
||||
:note="item.code"
|
||||
arrow
|
||||
hover
|
||||
@click="router.push(`/management/permissions/roles/${item.id}`)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-text="item.name" :style="{ paddingLeft: `${item.level * 1.25}rem` }" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<template #right>
|
||||
<t-button v-if="canDeleteRole(item)" v-can="corePermissionCodes.role.delete" class="delete" theme="danger" @click="removeRole(item.id)">删除</t-button>
|
||||
</template>
|
||||
</t-cell>
|
||||
<template #right>
|
||||
<t-button v-if="canDeleteRole(item)" v-can="corePermissionCodes.role.delete" class="delete" theme="danger" @click="removeRole(item.id)">删除</t-button>
|
||||
</template>
|
||||
</t-swipe-cell>
|
||||
</t-swipe-cell>
|
||||
</t-cell-group>
|
||||
<t-empty v-else-if="!permissionStore.loading" description="暂无角色" />
|
||||
</t-pull-down-refresh>
|
||||
|
||||
@@ -24,21 +24,22 @@
|
||||
class="list"
|
||||
theme="card"
|
||||
>
|
||||
<t-cell
|
||||
:class="{ inherited: isPermissionInherited(item.id) }"
|
||||
v-for="item in grantablePermissionList"
|
||||
:key="item.id"
|
||||
:title="item.name"
|
||||
:description="item.code"
|
||||
>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
:disabled="!canUpdateRolePermission || !canEditActiveRole || isPermissionInherited(item.id)"
|
||||
:model-value="isPermissionEnabled(item.id)"
|
||||
@change="value => setPermissionChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in grantablePermissionList"
|
||||
:key="item.id"
|
||||
:class="{ inherited: isPermissionInherited(item.id) }"
|
||||
:title="item.name"
|
||||
:description="item.code"
|
||||
>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
:disabled="!canUpdateRolePermission || !canEditActiveRole || isPermissionInherited(item.id)"
|
||||
:model-value="isPermissionEnabled(item.id)"
|
||||
@change="value => setPermissionChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-empty v-else-if="!permissionStore.loading" description="暂无可配置的直接权限 P" />
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.point.accountRead" class="point-account-detail">
|
||||
<card-container v-if="customer">
|
||||
<card-container v-if="customer" v-entrance-transition>
|
||||
<customer-profile-card :customer="customer" />
|
||||
</card-container>
|
||||
<section v-if="account" class="account-card">
|
||||
<section v-if="account" class="account-card" v-entrance-transition="70">
|
||||
<div class="header">
|
||||
<div>积分卡</div>
|
||||
<div class="time dark-white" v-text="formatTimestamp(account.createdAt!)" />
|
||||
@@ -14,15 +14,13 @@
|
||||
</div>
|
||||
<div class="id" v-text="account.id?.toUpperCase()" />
|
||||
</section>
|
||||
|
||||
<t-cell-group v-if="account" title="积分统计" theme="card">
|
||||
<t-cell-group v-if="account" title="积分统计" theme="card" v-entrance-transition="140">
|
||||
<t-cell title="累计获得" :note="formatPoints(account.totalEarned)" />
|
||||
<t-cell title="累计消耗" :note="formatPoints(account.totalConsumed)" />
|
||||
<t-cell title="累计撤销" :note="formatPoints(account.totalRevoked)" />
|
||||
<t-cell title="人工调整" :note="formatSignedPoints(account.totalAdjusted)" />
|
||||
</t-cell-group>
|
||||
|
||||
<section v-if="customer" class="actions">
|
||||
<section v-if="customer" class="actions" v-entrance-transition="210">
|
||||
<t-button
|
||||
v-can="permissionCodes.point.ledgerRead"
|
||||
class="bg-white"
|
||||
@@ -40,7 +38,6 @@
|
||||
人工调整积分
|
||||
</t-button>
|
||||
</section>
|
||||
|
||||
<t-empty v-if="!account" :description="isLoading ? '正在加载积分账户' : '积分账户不存在或已被删除'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -16,23 +16,24 @@
|
||||
@scrolltolower="load"
|
||||
>
|
||||
<t-cell-group v-if="pageResult.list.length" class="list" theme="card">
|
||||
<customer-cell
|
||||
v-for="item in pageResult.list"
|
||||
:key="item.id"
|
||||
:customer="item.customer"
|
||||
class="item"
|
||||
arrow
|
||||
hover
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #description>
|
||||
<span>余额:</span>
|
||||
<span
|
||||
class="balance"
|
||||
:class="getBalanceTheme(item.balance)"
|
||||
v-text="formatPoints(item.balance)" />
|
||||
</template>
|
||||
</customer-cell>
|
||||
<customer-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
:customer="item.customer"
|
||||
class="item"
|
||||
arrow
|
||||
hover
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #description>
|
||||
<span>余额:</span>
|
||||
<span
|
||||
class="balance"
|
||||
:class="getBalanceTheme(item.balance)"
|
||||
v-text="formatPoints(item.balance)" />
|
||||
</template>
|
||||
</customer-cell>
|
||||
</t-cell-group>
|
||||
<div class="load-state" v-text="loadStateText" />
|
||||
</t-pull-down-refresh>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
visible
|
||||
content="人工调整会追加一条不可修改的 ADJUST 流水,请填写真实、明确的调整原因。"
|
||||
/>
|
||||
<t-form class="form" label-align="left" label-width="7rem">
|
||||
<t-form class="form" label-align="left" label-width="7rem" v-entrance-transition>
|
||||
<t-form-item label="客户" required-mark>
|
||||
<div class="customer-actions">
|
||||
<t-button
|
||||
@@ -58,11 +58,17 @@
|
||||
<span class="request-id" v-text="adjustRequestId" />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<div class="bottom-actions">
|
||||
<t-button theme="primary" :loading="isSaving" :disabled="!canSubmit" @click="submitAdjust">
|
||||
提交调整
|
||||
</t-button>
|
||||
</div>
|
||||
<t-button
|
||||
class="cell-button"
|
||||
theme="primary"
|
||||
:loading="isSaving"
|
||||
:disabled="!canSubmit"
|
||||
block
|
||||
v-entrance-transition="70"
|
||||
@click="submitAdjust"
|
||||
>
|
||||
提交调整
|
||||
</t-button>
|
||||
<customer-selector
|
||||
v-model="selectedCustomerId"
|
||||
v-model:visible="selectorVisible"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.point.ledgerRead" class="point-ledger-detail">
|
||||
<div v-if="customer" v-can="permissionCodes.point.ledgerRead" class="point-ledger-detail">
|
||||
<customer-profile-card
|
||||
v-if="customer"
|
||||
class="customer-profile"
|
||||
:customer="customer"
|
||||
v-entrance-transition
|
||||
@click="toCustomerDetail"
|
||||
/>
|
||||
<template v-if="ledger">
|
||||
<t-cell-group title="积分流水" theme="card">
|
||||
<t-cell-group title="积分流水" theme="card" v-entrance-transition="70">
|
||||
<t-cell title="流水类型">
|
||||
<template #note>
|
||||
<t-tag
|
||||
@@ -26,8 +26,7 @@
|
||||
</t-cell>
|
||||
<t-cell title="流水备注" :note="Text.display(ledger.remark)" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group title="触发事件" theme="card">
|
||||
<t-cell-group title="触发事件" theme="card" v-entrance-transition="140">
|
||||
<template v-if="triggerEvent">
|
||||
<t-cell title="事件名称" :note="triggerEvent.name || '未命名事件'" />
|
||||
<t-cell title="事件类型" :note="getEventValueTypeText(triggerEvent)" />
|
||||
@@ -36,8 +35,7 @@
|
||||
</template>
|
||||
<div v-else class="empty" v-text="getEventEmptyText()" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group title="事件记录" theme="card">
|
||||
<t-cell-group title="事件记录" theme="card" v-entrance-transition="210">
|
||||
<template v-if="eventRecord">
|
||||
<t-cell title="登记事件" :note="eventRecord.event?.name || triggerEvent?.name || '未知事件'" />
|
||||
<t-cell title="登记时间">
|
||||
@@ -54,8 +52,7 @@
|
||||
</template>
|
||||
<div v-else class="empty" v-text="getRecordEmptyText()" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group title="命中规则" theme="card">
|
||||
<t-cell-group title="命中规则" theme="card" v-entrance-transition="280">
|
||||
<template v-if="hitRule">
|
||||
<t-cell title="规则名称" :note="hitRule.name || '未命名规则'" />
|
||||
<t-cell title="触发类型" :note="getTriggerTypeText(hitRule.triggerType)" />
|
||||
|
||||
@@ -72,45 +72,46 @@
|
||||
@scrolltolower="load"
|
||||
>
|
||||
<t-cell-group v-if="pageResult.list.length" class="list" theme="card">
|
||||
<t-cell
|
||||
v-for="item in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:arrow="!!item.id"
|
||||
:hover="!!item.id"
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-image
|
||||
v-if="getCustomerPhotoURL(item.customer!, 64)"
|
||||
:src="getCustomerPhotoURL(item.customer!, 64)"
|
||||
fit="cover"
|
||||
class="avatar"
|
||||
/>
|
||||
<div v-else class="avatar fallback" v-text="(item.customer?.name || item.customer?.code || '客').slice(0, 1)" />
|
||||
</template>
|
||||
<template #title>
|
||||
<div class="title">
|
||||
<t-tag
|
||||
class="type-icon"
|
||||
:theme="item.pointDelta && 0 < item.pointDelta ? 'success' : 'danger'"
|
||||
:content="getLedgerShortType(item)"
|
||||
variant="outline"
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:arrow="!!item.id"
|
||||
:hover="!!item.id"
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-image
|
||||
v-if="getCustomerPhotoURL(item.customer!, 64)"
|
||||
:src="getCustomerPhotoURL(item.customer!, 64)"
|
||||
fit="cover"
|
||||
class="avatar"
|
||||
/>
|
||||
<div class="name" v-text="item.customer?.name" />
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<div v-text="`时间:${Time.toPassedDateTime(item.occurredAt)}`" />
|
||||
<div v-text="`余额:${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`" />
|
||||
<div v-text="item.remark" />
|
||||
</div>
|
||||
</template>
|
||||
<template #note>
|
||||
<div class="delta keep-text" :class="getLedgerTheme(item)" v-text="getLedgerDelta(item)" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<div v-else class="avatar fallback" v-text="(item.customer?.name || item.customer?.code || '客').slice(0, 1)" />
|
||||
</template>
|
||||
<template #title>
|
||||
<div class="title">
|
||||
<t-tag
|
||||
class="type-icon"
|
||||
:theme="item.pointDelta && 0 < item.pointDelta ? 'success' : 'danger'"
|
||||
:content="getLedgerShortType(item)"
|
||||
variant="outline"
|
||||
/>
|
||||
<div class="name" v-text="item.customer?.name" />
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<div v-text="`时间:${Time.toPassedDateTime(item.occurredAt)}`" />
|
||||
<div v-text="`余额:${item.balanceBefore ?? 0} → ${item.balanceAfter ?? 0}`" />
|
||||
<div v-text="item.remark" />
|
||||
</div>
|
||||
</template>
|
||||
<template #note>
|
||||
<div class="delta keep-text" :class="getLedgerTheme(item)" v-text="getLedgerDelta(item)" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<div class="load-state" v-text="loadStateText" />
|
||||
</t-pull-down-refresh>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.pointRule.read" class="point-rule-detail">
|
||||
<section v-if="rule" class="rule-header">
|
||||
<section v-if="rule" class="rule-header" v-entrance-transition>
|
||||
<div class="point-icon" :class="{ consume: isConsumeRule }">
|
||||
<t-icon name="money" size="1.75rem" />
|
||||
</div>
|
||||
@@ -12,12 +12,11 @@
|
||||
<div class="point-value" v-text="rulePointText" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<t-cell-group v-if="rule" title="基本信息" theme="card">
|
||||
<t-cell-group v-if="rule" title="基本信息" theme="card" v-entrance-transition="70">
|
||||
<t-cell title="所属门店" :note="storeName" />
|
||||
<t-cell
|
||||
title="登记事件"
|
||||
:note="event?.name || rule.eventId || '未绑定事件'"
|
||||
:note="event?.name || '未绑定事件'"
|
||||
:arrow="canReadEvent && !!event?.id"
|
||||
:hover="canReadEvent && !!event?.id"
|
||||
@click="toEventDetail"
|
||||
@@ -30,8 +29,7 @@
|
||||
</t-cell>
|
||||
<t-cell title="规则备注" :note="Text.display(rule.remark)" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="rule" title="积分配置" theme="card">
|
||||
<t-cell-group v-if="rule" title="积分配置" theme="card" v-entrance-transition="140">
|
||||
<t-cell title="触发类型" :note="getTriggerText(rule.triggerType)" />
|
||||
<t-cell title="积分值模式" :note="getModeText(rule.pointMode)" />
|
||||
<t-cell v-if="rule.pointMode === 'FIXED'" title="固定积分" :note="formatPointValue(rule.pointValue)" />
|
||||
@@ -45,12 +43,15 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="tierTextList.length" title="积分分档" theme="card">
|
||||
<t-cell-group
|
||||
v-if="tierTextList.length"
|
||||
title="积分分档"
|
||||
theme="card"
|
||||
v-entrance-transition="210"
|
||||
>
|
||||
<t-cell v-for="(text, index) in tierTextList" :key="index" :title="`第 ${index + 1} 档`" :note="text" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="rule" title="其他配置" theme="card">
|
||||
<t-cell-group v-if="rule" title="其他配置" theme="card" v-entrance-transition="280">
|
||||
<t-cell title="规则优先级" :note="formatNumber(rule.priority)" />
|
||||
<t-cell title="命中后停止匹配" :note="rule.exclusive ? '是' : '否'" />
|
||||
<t-cell title="生效开始" :note="formatDate(rule.beginAt)" />
|
||||
@@ -58,7 +59,6 @@
|
||||
<t-cell title="创建时间" :note="formatDate(rule.createdAt, '未知时间')" />
|
||||
<t-cell title="更新时间" :note="formatDate(rule.updatedAt, '未知时间')" />
|
||||
</t-cell-group>
|
||||
|
||||
<t-empty v-else :description="isLoading ? '正在加载积分规则' : '积分规则不存在'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div v-can="pageAccess" class="point-rule-edit">
|
||||
<t-form class="form" label-align="left" label-width="7rem">
|
||||
<card-container>
|
||||
<card-container v-entrance-transition>
|
||||
<t-form-item v-if="isGlobalManager" label="门店" required-mark :arrow="isCreateMode" @click="openStorePicker">
|
||||
<span class="picker-text" v-text="selectedStoreName" />
|
||||
</t-form-item>
|
||||
@@ -18,7 +18,7 @@
|
||||
<t-textarea v-model.trim="formModel.remark" :autosize="{ minRows: 3, maxRows: 5 }" placeholder="规则说明" />
|
||||
</t-form-item>
|
||||
</card-container>
|
||||
<card-container>
|
||||
<card-container v-entrance-transition="70">
|
||||
<t-form-item label="触发类型" arrow @click="openTriggerPicker">
|
||||
<span class="picker-text" v-text="getTriggerText(formModel.triggerType)" />
|
||||
</t-form-item>
|
||||
@@ -68,7 +68,7 @@
|
||||
<point-rule-tier-editor v-model="formModel.tiers" :value-unit="selectedSourceValueUnit" />
|
||||
</template>
|
||||
</card-container>
|
||||
<card-container>
|
||||
<card-container v-entrance-transition="140">
|
||||
<t-form-item label="生效开始" arrow @click="openBeginAtPicker">
|
||||
<div class="time-value">
|
||||
<span class="picker-text" v-text="formModel.beginAtText || '不限'" />
|
||||
@@ -82,24 +82,23 @@
|
||||
</div>
|
||||
</t-form-item>
|
||||
</card-container>
|
||||
<card-container tips="命中规则并执行积分动作后不再匹配后续规则">
|
||||
<card-container tips="命中规则并执行积分动作后不再匹配后续规则" v-entrance-transition="210">
|
||||
<t-form-item label="独占匹配" content-align="right">
|
||||
<t-switch size="small" v-model="formModel.exclusive" />
|
||||
</t-form-item>
|
||||
</card-container>
|
||||
</t-form>
|
||||
<div v-if="!isCreateMode" class="bottom-actions">
|
||||
<t-button
|
||||
v-can="permissionCodes.pointRule.delete"
|
||||
class="delete bg-white"
|
||||
theme="danger"
|
||||
variant="outline"
|
||||
:loading="isRemoving"
|
||||
@click="confirmRemove"
|
||||
>
|
||||
删除
|
||||
</t-button>
|
||||
</div>
|
||||
<t-button
|
||||
v-if="!isCreateMode"
|
||||
class="delete red bg-white cell-button"
|
||||
v-can="permissionCodes.pointRule.delete"
|
||||
:loading="isRemoving"
|
||||
variant="text"
|
||||
block
|
||||
@click="confirmRemove"
|
||||
>
|
||||
删除
|
||||
</t-button>
|
||||
</div>
|
||||
<t-popup v-model="storePickerVisible" placement="bottom">
|
||||
<t-picker
|
||||
@@ -268,7 +267,7 @@ const formModel = reactive({
|
||||
|
||||
const eventList = ref<EventItem[]>([]);
|
||||
const selectedStoreName = computed(() => currentStoreStore.storeList.find(item => item.id === formModel.storeId)?.name || "请选择门店");
|
||||
const selectedEventName = computed(() => eventList.value.find(item => item.id === formModel.eventId)?.name || (formModel.eventId ? `事件 ${formModel.eventId}` : "请选择登记事件"));
|
||||
const selectedEventName = computed(() => eventList.value.find(item => item.id === formModel.eventId)?.name || "请选择登记事件");
|
||||
const storePickerVisible = ref(false);
|
||||
const storePickerDraft = ref<PickerValue[]>([]);
|
||||
const storePickerColumns = computed(() => [
|
||||
@@ -295,7 +294,7 @@ const sourceEventPickerColumns = computed(() => [
|
||||
]);
|
||||
const selectedSourceEventName = computed(() => selectedSourceEvent.value
|
||||
? `${selectedSourceEvent.value.name || "未命名事件"}(${getEventValueUnitText(selectedSourceEvent.value.valueUnit)})`
|
||||
: formModel.sourceEventId ? `事件 ${formModel.sourceEventId}` : "请选择来源事件");
|
||||
: "请选择来源事件");
|
||||
|
||||
let tierKey = 0;
|
||||
|
||||
@@ -922,14 +921,8 @@ onUnmounted(() => navBarStore.clearRight());
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
margin: 0 1rem;
|
||||
padding-top: 1rem;
|
||||
display: flex;
|
||||
|
||||
.delete {
|
||||
width: 100%;
|
||||
}
|
||||
.delete {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
>
|
||||
<t-cell-group v-if="pageResult.list.length" class="list" theme="card">
|
||||
<t-cell
|
||||
v-for="item in pageResult.list"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
:arrow="!!item.id"
|
||||
:hover="!!item.id"
|
||||
v-entrance-transition="index * 30"
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #left-icon>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.pointRule.update" class="point-rule-sort">
|
||||
<div class="tip" v-text="'按住右侧拖动手柄调整规则顺序,保存后生效;仅显示启用规则'" />
|
||||
<div class="tip" v-text="'按住右侧拖动手柄调整规则顺序,保存后生效;仅显示启用规则'" v-entrance-transition />
|
||||
<div class="items">
|
||||
<t-cell-group v-if="ruleList.length" theme="card">
|
||||
<vue-draggable-next
|
||||
@@ -15,7 +15,12 @@
|
||||
:disabled="isLoading || isSaving"
|
||||
@change="sortDirty = true"
|
||||
>
|
||||
<t-cell v-for="item in ruleList" :key="item.id" class="cell">
|
||||
<t-cell
|
||||
class="cell"
|
||||
v-for="(item, index) in ruleList"
|
||||
:key="item.id"
|
||||
v-entrance-transition="index * 30"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-text="item.name || '未命名规则'" />
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="settings-page">
|
||||
<t-cell-group title="显示" theme="card">
|
||||
<t-cell-group title="显示" theme="card" v-entrance-transition>
|
||||
<t-cell class="theme" title="显示模式">
|
||||
<template #right-icon>
|
||||
<segmented-slider
|
||||
@@ -12,7 +12,7 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group title="声音" theme="card">
|
||||
<t-cell-group title="声音" theme="card" v-entrance-transition="70">
|
||||
<t-cell title="扫码成功">
|
||||
<template #right-icon>
|
||||
<t-switch :model-value="settingStore.sound.scanSuccess" @change="value => handleScanSuccessChange(value === true)" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
v-can="permissionCodes.store.read"
|
||||
class="store-business-day-calendar"
|
||||
>
|
||||
<header class="summary bg-white">
|
||||
<header class="summary bg-white" v-entrance-transition>
|
||||
<header class="header">
|
||||
<div class="text-bold" v-text="store.name" />
|
||||
<t-tag variant="outline" :content="store.code" />
|
||||
@@ -18,6 +18,7 @@
|
||||
class="calendar-card"
|
||||
description="设置门店休息日,该日无任何登记记录不视为中断连续登记事件。已有登记不可设为休息,标记休息不能产生登记"
|
||||
tips="点击日期即可新增营休日"
|
||||
v-entrance-transition="70"
|
||||
>
|
||||
<t-calendar
|
||||
:key="calendarRenderKey"
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
<template>
|
||||
<div v-can="permissionCodes.stat.read" class="data-charts-page">
|
||||
<store-chart-summary :date-text-list="dateTextList" />
|
||||
|
||||
<store-event-record-calendar-section @list="toEventRecordList" />
|
||||
<store-event-record-trend-chart :date-text-list="dateTextList" />
|
||||
<store-event-record-number-value-chart :date-text-list="dateTextList" />
|
||||
<store-event-structure-chart :date-text-list="dateTextList" />
|
||||
<store-customer-growth-chart :date-text-list="dateTextList" />
|
||||
<store-customer-gender-chart />
|
||||
<store-chart-summary v-entrance-transition :date-text-list="dateTextList" />
|
||||
<store-event-record-calendar-section v-entrance-transition="70" @list="toEventRecordList" />
|
||||
<store-event-record-trend-chart v-entrance-transition="140" :date-text-list="dateTextList" />
|
||||
<store-event-record-number-value-chart v-entrance-transition="210" :date-text-list="dateTextList" />
|
||||
<store-event-structure-chart v-entrance-transition="280" :date-text-list="dateTextList" />
|
||||
<store-customer-growth-chart v-entrance-transition="350" :date-text-list="dateTextList" />
|
||||
<store-customer-gender-chart v-entrance-transition="420" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-can="savePermissionCode" class="store-edit">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form class="form" label-align="left" v-entrance-transition>
|
||||
<t-form-item v-if="!isStoreManagerScope" label="编码">
|
||||
<t-input v-model.trim="formData.code" placeholder="门店编码" borderless />
|
||||
</t-form-item>
|
||||
@@ -20,7 +20,7 @@
|
||||
<t-textarea v-model.trim="formData.remark" class="textarea" placeholder="备注" autosize borderless />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-cell-group v-if="!isCreateMode" theme="card">
|
||||
<t-cell-group v-if="!isCreateMode" theme="card" v-entrance-transition="70">
|
||||
<t-cell
|
||||
title="营业日管理"
|
||||
note="配置营业或休息日期"
|
||||
@@ -36,7 +36,7 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<div v-if="!isCreateMode && !isStoreManagerScope" class="actions">
|
||||
<div v-if="!isCreateMode && !isStoreManagerScope" class="actions" v-entrance-transition="140">
|
||||
<t-button
|
||||
v-can="permissionCodes.store.delete"
|
||||
class="action"
|
||||
|
||||
@@ -8,26 +8,27 @@
|
||||
@scrolltolower="fetch"
|
||||
>
|
||||
<t-cell-group theme="card">
|
||||
<t-cell
|
||||
class="item"
|
||||
v-for="item in pageResult.list"
|
||||
:key="item.id"
|
||||
arrow
|
||||
@click="toEdit(item)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<div class="text-bold" v-text="item.name || '未命名门店'"></div>
|
||||
<t-tag size="small" :theme="getStoreStatusTheme(item.status)" variant="outline" :content="getStoreStatusText(item.status)" />
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<span class="gray" v-text="item.telephone ? `电话:${item.telephone}` : '电话:-'" />
|
||||
<span class="gray" v-text="item.address ? `地址:${item.address}` : '地址:-'" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
arrow
|
||||
@click="toEdit(item)"
|
||||
>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<div class="text-bold" v-text="item.name || '未命名门店'"></div>
|
||||
<t-tag size="small" :theme="getStoreStatusTheme(item.status)" variant="outline" :content="getStoreStatusText(item.status)" />
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<div class="description">
|
||||
<span class="gray" v-text="item.telephone ? `电话:${item.telephone}` : '电话:-'" />
|
||||
<span class="gray" v-text="item.address ? `地址:${item.address}` : '地址:-'" />
|
||||
</div>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<div v-if="!pageResult.list.length" class="empty-block" v-text="isLoading ? '正在加载门店' : '暂无门店'" />
|
||||
<div v-if="pageResult.list.length" class="load-state" v-text="isNoMore ? '已加载全部门店' : '上拉加载更多'" />
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
<template>
|
||||
<div class="entry-page">
|
||||
<section class="entry-list">
|
||||
<div v-for="item in visibleEntryList" :key="item.path" class="item" @click="go(item.path)">
|
||||
<div class="body">
|
||||
<t-icon :name="item.icon" size="1.75rem" />
|
||||
<h2 v-text="item.title" />
|
||||
<div
|
||||
v-entrance-transition="index * 70"
|
||||
v-for="(item, index) in visibleEntryList"
|
||||
:key="item.path"
|
||||
class="item"
|
||||
@click="go(item.path)"
|
||||
>
|
||||
<div class="body">
|
||||
<t-icon :name="item.icon" size="1.75rem" />
|
||||
<h2 v-text="item.title" />
|
||||
</div>
|
||||
<p v-text="item.desc" />
|
||||
</div>
|
||||
<p v-text="item.desc" />
|
||||
</div>
|
||||
</section>
|
||||
<div class="tips gray">微信内打开本站可能会经常在扫码时需要授权,建议使用浏览器打开(右上角菜单,使用默认浏览器打开),并添加快捷入口到桌面。</div>
|
||||
<div class="tips gray" v-entrance-transition="visibleEntryList.length * 70">微信内打开本站可能会经常在扫码时需要授权,建议使用浏览器打开(右上角菜单,使用默认浏览器打开),并添加快捷入口到桌面。</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="management-tab">
|
||||
<t-cell-group class="user-card" theme="card">
|
||||
<t-cell-group class="user-card" theme="card" v-entrance-transition>
|
||||
<t-cell
|
||||
v-if="currentUser"
|
||||
class="info"
|
||||
@@ -38,7 +38,13 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-cell-group v-for="group in visibleMenuGroupList" :key="group.title" :title="group.title" theme="card">
|
||||
<t-cell-group
|
||||
v-for="(group, index) in visibleMenuGroupList"
|
||||
:key="group.title"
|
||||
:title="group.title"
|
||||
theme="card"
|
||||
v-entrance-transition="index * 70"
|
||||
>
|
||||
<t-cell
|
||||
v-for="item in group.items"
|
||||
:key="item.path"
|
||||
|
||||
+36
-36
@@ -1,41 +1,41 @@
|
||||
<template>
|
||||
<div class="store-tab">
|
||||
<section v-if="canViewStore || canManageStore" class="store-header">
|
||||
<t-cell-group class="store-card" theme="card">
|
||||
<t-cell
|
||||
v-if="canViewStore"
|
||||
class="info"
|
||||
:title="currentStoreStore.currentStoreName"
|
||||
:description="currentStore?.address"
|
||||
/>
|
||||
<t-cell
|
||||
v-if="canSelectStore"
|
||||
class="action"
|
||||
title="切换门店"
|
||||
note="选择使用门店"
|
||||
arrow
|
||||
hover
|
||||
@click="openStorePicker"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="swap" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-if="canManageStore"
|
||||
class="action"
|
||||
title="门店管理"
|
||||
note="管理门店资料和营业日"
|
||||
arrow
|
||||
hover
|
||||
@click="goStoreManagement"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="shop-3" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
</section>
|
||||
<section v-entrance-transition v-if="canViewStore || canManageStore" class="store-header">
|
||||
<t-cell-group class="store-card" theme="card">
|
||||
<t-cell
|
||||
v-if="canViewStore"
|
||||
class="info"
|
||||
:title="currentStoreStore.currentStoreName"
|
||||
:description="currentStore?.address"
|
||||
/>
|
||||
<t-cell
|
||||
v-if="canSelectStore"
|
||||
class="action"
|
||||
title="切换门店"
|
||||
note="选择使用门店"
|
||||
arrow
|
||||
hover
|
||||
@click="openStorePicker"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="swap" />
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-if="canManageStore"
|
||||
class="action"
|
||||
title="门店管理"
|
||||
note="管理门店资料和营业日"
|
||||
arrow
|
||||
hover
|
||||
@click="goStoreManagement"
|
||||
>
|
||||
<template #leftIcon>
|
||||
<t-icon name="shop-3" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
</section>
|
||||
<store-data-charts :key="currentStoreStore.currentStoreId" />
|
||||
<t-popup v-model="storePickerVisible" placement="bottom">
|
||||
<t-picker
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
>
|
||||
<div class="tag-panel">
|
||||
<div
|
||||
v-for="item in tagList"
|
||||
:key="item.id"
|
||||
v-entrance-transition="index * 10"
|
||||
class="item bg-white"
|
||||
v-for="(item, index) in tagList"
|
||||
:key="item.id"
|
||||
@click="openEditDialog(item)"
|
||||
>
|
||||
<span class="name" v-text="getTagName(item)" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="register-page">
|
||||
<section v-if="isLoading" class="register-panel"><t-loading text="正在校验邀请码" /></section>
|
||||
<section v-else-if="!isValid" class="register-panel invalid">
|
||||
<section v-else-if="!isValid" class="register-panel invalid" v-entrance-transition>
|
||||
<div class="brand">
|
||||
<logo />
|
||||
<h1>糕店客户管理</h1>
|
||||
@@ -10,11 +10,11 @@
|
||||
<p class="tips gray" v-text="invalidMessage" />
|
||||
</section>
|
||||
<section v-else class="register-panel">
|
||||
<div class="brand">
|
||||
<div class="brand" v-entrance-transition>
|
||||
<logo />
|
||||
<h1>加入糕店客户管理系统</h1>
|
||||
</div>
|
||||
<p class="tips gray" v-text="expireText" />
|
||||
<p class="tips gray" v-text="expireText" v-entrance-transition="70" />
|
||||
<t-form class="form" label-align="left" label-width="6rem">
|
||||
<t-form-item label="手机号">
|
||||
<t-input v-model.trim="formModel.phoneNo" type="tel" inputmode="tel" borderless placeholder="请输入手机号" />
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
<div class="login-page">
|
||||
<section class="login-panel">
|
||||
<div class="brand">
|
||||
<logo />
|
||||
<h1>糕店客户管理</h1>
|
||||
<logo v-entrance-transition />
|
||||
<h1 v-entrance-transition="70">糕店客户管理</h1>
|
||||
</div>
|
||||
<t-segmented class="login-type" v-model="loginType" :options="loginTypeOptions" />
|
||||
<t-segmented
|
||||
class="login-type"
|
||||
v-model="loginType"
|
||||
:options="loginTypeOptions"
|
||||
v-entrance-transition="140"
|
||||
/>
|
||||
<password-login v-if="loginType === 'password'" class="form" />
|
||||
<sms-login v-else class="form" />
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
v-can="permissionCodes.user.read"
|
||||
class="user-edit"
|
||||
>
|
||||
<t-cell-group v-if="managedUser.user" theme="card">
|
||||
<t-cell-group v-if="managedUser.user" theme="card" v-entrance-transition>
|
||||
<t-cell
|
||||
:title="managedUser.user.name"
|
||||
:description="getRoleDisplayName(getManagedUserRoleList(managedUser)[0], permissionStore.roleList)"
|
||||
@@ -19,8 +19,7 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="managedUser.user" theme="card">
|
||||
<t-cell-group v-if="managedUser.user" theme="card" v-entrance-transition="70">
|
||||
<t-cell title="状态" :note="managedUser.enabled ? '启用' : '禁用'" />
|
||||
<t-cell title="备注" :note="managedUser.remark" />
|
||||
<t-cell title="手机号">
|
||||
@@ -34,8 +33,7 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="currentUser" theme="card">
|
||||
<t-cell-group v-if="currentUser" theme="card" v-entrance-transition="140">
|
||||
<t-cell
|
||||
v-can="permissionCodes.user.update"
|
||||
title="配置角色"
|
||||
@@ -49,8 +47,7 @@
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
|
||||
<t-cell-group v-if="currentUser" title="可登记事件" theme="card">
|
||||
<t-cell-group v-if="currentUser" title="可登记事件" theme="card" v-entrance-transition="210">
|
||||
<t-cell v-for="item in scopeList" :key="item.id" :title="item.name"/>
|
||||
<t-cell v-if="!scopeList.length" title="未配置" />
|
||||
</t-cell-group>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<div class="poster-page">
|
||||
<section class="poster-wrap">
|
||||
<section class="poster-wrap" v-entrance-transition>
|
||||
<img v-if="posterImage" class="poster" :src="posterImage" alt="邀请注册海报" />
|
||||
<div v-else class="empty" v-text="message" />
|
||||
</section>
|
||||
<div v-if="posterImage" class="actions">
|
||||
<div
|
||||
class="tips gray"
|
||||
v-entrance-transition="70"
|
||||
>微信内可能无法发起下载海报,可长按保存为图片、转发连接或使用默认浏览器打开</div>
|
||||
<div v-if="posterImage" class="actions" v-entrance-transition="140">
|
||||
<t-button
|
||||
class="button bg-white"
|
||||
variant="outline"
|
||||
@@ -18,7 +22,7 @@
|
||||
block
|
||||
:loading="isDownloading"
|
||||
@click="savePoster"
|
||||
>保存海报</t-button>
|
||||
>下载海报</t-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -110,6 +114,11 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: .875rem;
|
||||
text-indent: 2em;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 5rem 1rem;
|
||||
color: var(--td-text-color-secondary);
|
||||
|
||||
+30
-29
@@ -10,36 +10,37 @@
|
||||
@scrolltolower="fetch"
|
||||
>
|
||||
<t-cell-group theme="card">
|
||||
<t-cell
|
||||
class="item"
|
||||
v-for="item in pageResult.list"
|
||||
:key="item.id"
|
||||
arrow
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #left-icon>
|
||||
<t-image :src="buildUserAvatar(item)" :alt="getUserName(item)" fit="cover" class="avatar" />
|
||||
</template>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<span class="name" v-text="getUserName(item)" />
|
||||
<div class="meta-list">
|
||||
<t-tag
|
||||
v-for="(roleName, index) in getRoleNameList(item)"
|
||||
:key="`${roleName}-${index}`"
|
||||
class="meta"
|
||||
size="small"
|
||||
theme="success"
|
||||
variant="outline"
|
||||
:content="roleName"
|
||||
/>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in pageResult.list"
|
||||
:key="item.id"
|
||||
class="item"
|
||||
arrow
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<template #left-icon>
|
||||
<t-image :src="buildUserAvatar(item)" :alt="getUserName(item)" fit="cover" class="avatar" />
|
||||
</template>
|
||||
<template #title>
|
||||
<div class="header">
|
||||
<span class="name" v-text="getUserName(item)" />
|
||||
<div class="meta-list">
|
||||
<t-tag
|
||||
v-for="(roleName, index) in getRoleNameList(item)"
|
||||
:key="`${roleName}-${index}`"
|
||||
class="meta"
|
||||
size="small"
|
||||
theme="success"
|
||||
variant="outline"
|
||||
:content="roleName"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #description>
|
||||
<telephone-link :value="item.user?.phoneNo" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</template>
|
||||
<template #description>
|
||||
<telephone-link :value="item.user?.phoneNo" />
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<div v-if="!pageResult.list.length" class="load-state" v-text="isLoading ? '正在加载用户' : '暂无用户'" />
|
||||
<div v-if="pageResult.list.length" class="load-state" v-text="isNoMore ? '已经到底了' : '上拉加载更多'" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="password-page">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form class="form" label-align="left" v-entrance-transition>
|
||||
<t-form-item label="旧密码">
|
||||
<t-input v-model.trim="formModel.oldPassword" type="password" placeholder="旧密码" borderless />
|
||||
</t-form-item>
|
||||
@@ -11,7 +11,13 @@
|
||||
<t-input v-model.trim="formModel.confirmPassword" type="password" placeholder="确认密码" borderless />
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-button class="save" theme="primary" :loading="isSaving" @click="savePassword">保存</t-button>
|
||||
<t-button
|
||||
class="save cell-button"
|
||||
theme="primary"
|
||||
:loading="isSaving"
|
||||
v-entrance-transition="70"
|
||||
@click="savePassword"
|
||||
>保存</t-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -63,7 +69,10 @@ async function savePassword(): Promise<void> {
|
||||
|
||||
<style scoped lang="less">
|
||||
.password-page {
|
||||
gap: 1rem;
|
||||
display: flex;
|
||||
padding: calc(var(--app-nav-height) + 1rem) 0 4rem 0;
|
||||
flex-direction: column;
|
||||
|
||||
.form {
|
||||
padding: .5rem 0;
|
||||
@@ -71,13 +80,6 @@ async function savePassword(): Promise<void> {
|
||||
box-shadow: var(--td-shadow-1);
|
||||
border-radius: 1.4rem;
|
||||
}
|
||||
|
||||
.save {
|
||||
left: 1rem;
|
||||
right: 1rem;
|
||||
bottom: calc(.75rem + env(safe-area-inset-bottom, 0));
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
|
||||
:global(html.theme-dark) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="profile-page">
|
||||
<t-form class="form" label-align="left">
|
||||
<t-form class="form" label-align="left" v-entrance-transition>
|
||||
<t-form-item label="头像">
|
||||
<photo-field
|
||||
v-model="formModel.avatar"
|
||||
@@ -33,13 +33,14 @@
|
||||
</div>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-cell-group theme="card">
|
||||
<t-cell-group theme="card" v-entrance-transition="70">
|
||||
<t-cell title="修改密码" arrow hover @click="toPassword" />
|
||||
</t-cell-group>
|
||||
<t-button
|
||||
class="red bg-white cell-button"
|
||||
variant="text"
|
||||
block
|
||||
v-entrance-transition="140"
|
||||
@click="confirmLogout"
|
||||
>退出登录</t-button>
|
||||
<input
|
||||
|
||||
@@ -18,20 +18,21 @@
|
||||
</t-dropdown-menu>
|
||||
</div>
|
||||
<t-cell-group v-if="activeUser && roleList.length" theme="card">
|
||||
<t-cell
|
||||
v-for="item in roleList"
|
||||
:key="item.id"
|
||||
:title="item.name"
|
||||
:description="item.code"
|
||||
>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
v-can="userRoleWriteAccess"
|
||||
:model-value="isRoleChecked(item.id)"
|
||||
@change="value => setRoleChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
<t-cell
|
||||
v-entrance-transition="index * 30"
|
||||
v-for="(item, index) in roleList"
|
||||
:key="item.id"
|
||||
:title="item.name"
|
||||
:description="item.code"
|
||||
>
|
||||
<template #right-icon>
|
||||
<t-switch
|
||||
v-can="userRoleWriteAccess"
|
||||
:model-value="isRoleChecked(item.id)"
|
||||
@change="value => setRoleChecked(item.id, value === true)"
|
||||
/>
|
||||
</template>
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
<t-empty v-else-if="!isLoading" description="暂无可授权角色" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user