fix list style

This commit is contained in:
Timi
2026-08-07 17:06:03 +08:00
parent 28b789eb86
commit 82e717e3c6
13 changed files with 130 additions and 120 deletions
+3
View File
@@ -44,6 +44,7 @@
<script setup lang="ts">
import {Toast} from "tdesign-mobile-vue";
import {Captcha, useUserStore} from "timi-web";
import {useCurrentStoreStore} from "@/store/currentStoreStore";
type CaptchaExpose = {
captchaId: string;
@@ -57,6 +58,7 @@ defineOptions({
const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const currentStoreStore = useCurrentStoreStore();
const formModel = reactive({
user: "",
password: "",
@@ -90,6 +92,7 @@ async function login(): Promise<void> {
password: formModel.password
}
});
await currentStoreStore.loadAfterLogin();
const redirect = typeof route.query.redirect === "string" ? route.query.redirect : "/management";
await router.replace(redirect);
} catch (error) {
+10 -2
View File
@@ -54,7 +54,7 @@
alt-text="客户照片"
:loading="customerPhotoUploading"
:preview="false"
@add="customerPhotoInputRef?.click"
@add="openCustomerPhotoPicker"
@clear="customerPhotoTempFileId = ''"
/>
</t-form-item>
@@ -78,7 +78,7 @@
title="登记事件照片"
v-model="recordPhotoList"
:loading="recordPhotoUploading"
@add="recordPhotoInputRef?.click"
@add="openRecordPhotoPicker"
/>
</div>
</t-form>
@@ -375,6 +375,10 @@ const customerPhotoTempFileId = ref("");
const customerPhotoInputRef = ref<HTMLInputElement>();
const customerPhotoUploading = ref(false);
function openCustomerPhotoPicker(): void {
customerPhotoInputRef.value?.click();
}
function syncCustomerPhoto(customer?: Customer): void {
customerPhotoTempFileId.value = "";
customerPhoto.value = getCustomerPhotoURL(customer);
@@ -406,6 +410,10 @@ async function handleCustomerPhotoSelected(event: Event): Promise<void> {
const recordPhotoInputRef = ref<HTMLInputElement>();
const recordPhotoUploading = ref(false);
const recordPhotoItemList = ref<QuickPhoto[]>([]);
function openRecordPhotoPicker(): void {
recordPhotoInputRef.value?.click();
}
const recordPhotoList = computed<string[]>({
get() {
return recordPhotoItemList.value.map(item => item.url);
+6 -1
View File
@@ -55,7 +55,7 @@
alt-text="客户照片"
:loading="isPhotoUploading"
:preview="false"
@add="photoInputRef?.click"
@add="openPhotoPicker"
@clear="photoTempFileId = ''"
/>
</t-form-item>
@@ -264,6 +264,10 @@ const selectedAreas = ref<BodyAreaValue>(createBodyAreaValue());
const formData = reactive<Customer>({
});
function openPhotoPicker(): void {
photoInputRef.value?.click();
}
const canSubmit = computed(() => formData.name?.trim());
async function loadDetail() {
@@ -334,6 +338,7 @@ async function doSubmit(): Promise<void> {
try {
formData.conditioningPart = selectedAreas.value;
formData.attachmentList = photoTempFileId.value ? [{
attachType: "PHOTO",
tempFileId: photoTempFileId.value
}] : undefined;
+43 -97
View File
@@ -9,53 +9,47 @@
borderless
/>
</div>
<section class="total">
<span class="gray">客户总数:</span>
<span class="text-bold" v-text="pageResult.total" />
</section>
<t-pull-down-refresh
class="list-wrapper"
v-model="isRefreshing"
class="list-refresh"
:refresh-timeout="30000"
@refresh="refresh"
@scrolltolower="fetch"
>
<section class="items">
<div
<t-cell-group class="items" theme="card">
<t-cell
class="item"
v-for="(item, index) in pageResult.list"
:key="item.id || item.code || index"
arrow
@click="router.push(`/management/customers/${item.id}`)"
>
<t-image v-if="getCustomerPhotoURL(item)" :src="getCustomerPhotoURL(item)" :alt="item.name" fit="cover" class="avatar" />
<div v-else class="avatar fallback" v-text="(item.name || item.code || '客').slice(0, 1)" />
<div class="content">
<div class="line">
<div class="name">
<h4 class="value" v-text="item.name" />
<template #left-icon>
<t-image
v-if="getCustomerPhotoURL(item)"
class="avatar"
:src="getCustomerPhotoURL(item)"
:alt="item.name"
fit="cover"
/>
<div v-else class="avatar fallback" v-text="(item.name || item.code || '客').slice(0, 1)" />
</template>
<template #title>
<div class="header">
<div class="left">
<div class="text-bold" v-text="item.name" />
<gender-icon :value="item.gender" size="1.125rem" />
</div>
<span class="meta gray" v-text="item.code || ''" />
<span class="gray" v-text="item.code || ''" />
</div>
<div class="line">
<div class="gray">
<template v-if="item.telephone">
<t-icon name="call" />
<telephone-link class="word-space" :value="item.telephone" />
</template>
</div>
<t-tag
size="small"
variant="outline"
theme="success"
:content="`${item.invitedCount} 位邀请`"
/>
</div>
</div>
</div>
<div v-if="!pageResult.list.length" class="empty-block" v-text="isLoading ? '正在加载客户' : '暂无客户数据'" />
<div v-if="pageResult.list.length" class="load-state" v-text="isLoading ? '正在加载更多' : isNoMore ? '已经到底了' : '上拉加载更多'" />
</section>
</template>
<template #description>
<telephone-link :value="item.telephone" />
</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="isLoading ? '正在加载更多' : isNoMore ? '已经到底了' : '上拉加载更多'" />
</t-pull-down-refresh>
<div class="bottom-actions">
<t-button
@@ -188,85 +182,37 @@ async function doExport(): Promise<void> {
}
}
.total {
display: flex;
margin-top: 1rem;
justify-content: center;
}
.list-wrapper {
padding: 1rem 0 4rem 0;
.items {
gap: .5rem;
padding: 1rem;
display: grid;
.items {
.item {
gap: .75rem;
padding: .5rem;
display: flex;
text-align: left;
background: #f7faff;
align-items: center;
border: 1px solid var(--td-border-level-1-color);
border-radius: .875rem;
justify-content: space-between;
.item {
padding: 10px;
.avatar {
flex: none;
width: 3.5rem;
height: 3.5rem;
border-radius: .5rem;
&.fallback {
color: #2563eb;
display: flex;
font-size: 1.25rem;
background: #dbeafe;
align-items: center;
font-weight: 600;
justify-content: center;
}
}
.content {
gap: .75rem;
flex: 1;
display: flex;
min-width: 0;
flex-direction: column;
justify-content: space-between;
.meta {
font-size: .875rem;
.avatar {
width: 3.5rem;
height: 3.5rem;
border-radius: .5rem;
}
.line {
.header {
gap: .5rem;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.name {
gap: .375rem;
display: flex;
align-items: center;
.value {
margin: 0;
.left {
gap: .5rem;
display: flex;
align-items: center;
}
}
}
}
}
.empty-block,
.load-state {
padding: 1rem;
color: #52607a;
text-align: center;
background: #f8fbff;
border-radius: 1rem;
}
.bottom-actions {
gap: .75rem;
left: 1rem;
+1 -7
View File
@@ -91,7 +91,7 @@
</template>
</t-swipe-cell>
</t-cell-group>
<div v-else class="empty-block" v-text="isLoading ? '正在加载登记事件记录' : '暂无登记事件记录'" />
<div v-else class="load-state" v-text="isLoading ? '正在加载登记事件记录' : '暂无登记事件记录'" />
<div v-if="pageResult.list.length" class="load-state" v-text="loadStateText" />
</t-pull-down-refresh>
</div>
@@ -595,12 +595,6 @@ onUnmounted(() => {
}
}
}
.empty-block,
.load-state {
color: #52607a;
text-align: center;
}
}
.export {
+1 -1
View File
@@ -111,7 +111,7 @@ async function prepareStoreScope(): Promise<void> {
}
const store = await currentStoreStore.loadLoginStore();
formModel.storeId = store.id || "";
formModel.storeId = store?.id || "";
}
async function fillForm(): Promise<void> {
+1 -1
View File
@@ -158,7 +158,7 @@ async function loadStoreScope(): Promise<void> {
}
const store = await currentStoreStore.loadLoginStore();
loginStoreId.value = store.id || "";
loginStoreId.value = store?.id || "";
}
async function loadData(): Promise<void> {
+1 -1
View File
@@ -154,7 +154,7 @@ async function loadStoreScope(): Promise<void> {
}
const store = await currentStoreStore.loadLoginStore();
loginStoreId.value = store.id || "";
loginStoreId.value = store?.id || "";
}
async function loadData(): Promise<void> {