update AIChart, customer followup, media selector
This commit is contained in:
@@ -0,0 +1,645 @@
|
||||
<template>
|
||||
<div v-can="pageAccess" class="follow-up-reminder-edit">
|
||||
<t-form class="form" label-width="6rem">
|
||||
<t-form-item label="客户" content-align="right" required-mark>
|
||||
<div class="customer-picker">
|
||||
<span v-if="!selectedCustomer" class="picker-text" v-text="'请选择客户'" />
|
||||
<t-button
|
||||
theme="primary"
|
||||
size="extra-small"
|
||||
content="选择"
|
||||
@click="customerSelectorVisible = true"
|
||||
/>
|
||||
</div>
|
||||
</t-form-item>
|
||||
<t-form-item v-if="selectedCustomer" label-width="0">
|
||||
<customer-profile-card class="customer-profile" :customer="selectedCustomer" />
|
||||
</t-form-item>
|
||||
<t-form-item
|
||||
label="负责人"
|
||||
content-align="right"
|
||||
required-mark
|
||||
arrow
|
||||
@click="responsibleSelectorVisible = true"
|
||||
>
|
||||
<span v-text="selectedResponsibleName" />
|
||||
</t-form-item>
|
||||
<t-form-item label="跟进内容" required-mark>
|
||||
<t-textarea
|
||||
v-model="formModel.content"
|
||||
class="textarea"
|
||||
:autosize="{ minRows: 1, maxRows: 8 }"
|
||||
maxlength="1000"
|
||||
borderless
|
||||
placeholder="请输入跟进内容"
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label-width="0">
|
||||
<media-selector
|
||||
:model-value="photoUrlList"
|
||||
v-model:photo-items="photoItems"
|
||||
:upload="uploadReminderPhotoList"
|
||||
:edit-mode="true"
|
||||
:loading="isSaving || isUploading"
|
||||
add-text="选择照片"
|
||||
:show-type-label="false"
|
||||
title="附件照片"
|
||||
/>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<t-form class="form">
|
||||
<t-form-item class="remind-at" label="提醒时间" content-align="right" required-mark>
|
||||
<span class="picker-text" v-text="formModel.remindAtText || '请选择提醒时间'" />
|
||||
</t-form-item>
|
||||
<t-form-item label-width="0" content-align="right">
|
||||
<t-radio-group
|
||||
v-model="selectedRemindAtPreset"
|
||||
@change="handleRemindAtPresetChange"
|
||||
>
|
||||
<t-radio :block="false" borderless value="tomorrow">明天</t-radio>
|
||||
<t-radio :block="false" borderless value="afterTomorrow">后天</t-radio>
|
||||
<t-radio :block="false" borderless value="custom">指定时间</t-radio>
|
||||
</t-radio-group>
|
||||
</t-form-item>
|
||||
<t-form-item label="站内通知" content-align="right">
|
||||
<t-switch
|
||||
size="small"
|
||||
:model-value="hasChannel('INTERNAL')"
|
||||
borderless
|
||||
@change="value => setChannel('INTERNAL', value === true)"
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label="短信通知" content-align="right">
|
||||
<t-switch
|
||||
size="small"
|
||||
:model-value="hasChannel('SMS')"
|
||||
:disabled="!canSelectSms"
|
||||
borderless
|
||||
@change="value => setChannel('SMS', value === true)"
|
||||
/>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
<div class="tips red"
|
||||
v-text="'提醒时间精确到分钟,不能早于当前时间。短信会在提醒日期 08:00 聚合发送,不会在你选择的精确时间发送。'" />
|
||||
<customer-selector
|
||||
v-model="formModel.customerId"
|
||||
v-model:visible="customerSelectorVisible"
|
||||
:store-id="customerPickerStoreId"
|
||||
@change="handleCustomerChange"
|
||||
/>
|
||||
<managed-user-selector
|
||||
v-model="formModel.responsibleUserId"
|
||||
v-model:visible="responsibleSelectorVisible"
|
||||
:store-id="responsiblePickerStoreId"
|
||||
@change="handleResponsibleChange"
|
||||
/>
|
||||
<t-popup v-model="remindAtPickerVisible" placement="bottom">
|
||||
<t-date-time-picker
|
||||
v-if="remindAtPickerVisible"
|
||||
v-model="remindAtDraftText"
|
||||
:start="minimumDateTimeText"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
:mode="['date', 'minute']"
|
||||
title="提醒时间"
|
||||
@cancel="cancelRemindAtPicker"
|
||||
@confirm="confirmRemindAt"
|
||||
/>
|
||||
</t-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Time } from "timi-web";
|
||||
import { AttachmentAPI, type User, useUserStore } from "timi-web-api";
|
||||
import CustomerProfileCard from "@/components/CustomerProfileCard.vue";
|
||||
import { Message } from "@/utils/message";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import FollowUpReminderAPI from "@/api/FollowUpReminderAPI";
|
||||
import CustomerAPI from "@/api/CustomerAPI";
|
||||
import CustomerSelector from "@/components/CustomerSelector.vue";
|
||||
import ManagedUserSelector from "@/pages/followUpReminder/component/ManagedUserSelector.vue";
|
||||
import MediaSelector from "@/components/mediaSelector/MediaSelector.vue";
|
||||
import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
||||
import { useNavBarStore } from "@/store/navBarStore";
|
||||
import type { Customer } from "@/types/Customer";
|
||||
import type { ManagedUser } from "@/types/ManagedUser";
|
||||
import type {
|
||||
FollowUpReminder,
|
||||
FollowUpReminderAttachment,
|
||||
FollowUpReminderNotifyChannel,
|
||||
FollowUpReminderPayload
|
||||
} from "@/types/FollowUpReminder";
|
||||
import type { PhotoItem } from "@/types/Photo";
|
||||
import { compressUploadImageList } from "@/utils/imageCompression";
|
||||
import { getAttachmentReadURL } from "@/utils/attachment";
|
||||
import { parseDateTime } from "@/utils/date";
|
||||
import { gaoRoleCodes, permissionCodes } from "@/utils/permission";
|
||||
|
||||
defineOptions({
|
||||
name: "FollowUpReminderEdit"
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const currentStoreStore = useCurrentStoreStore();
|
||||
const navBarStore = useNavBarStore();
|
||||
|
||||
const routeId = computed(() => String(route.params.id || ""));
|
||||
const isEditMode = computed(() => !!routeId.value);
|
||||
const pageAccess = computed(() => isEditMode.value
|
||||
? permissionCodes.customerFollowUpReminder.update
|
||||
: permissionCodes.customerFollowUpReminder.create);
|
||||
|
||||
// ---------- 表单 ----------
|
||||
|
||||
const isSaving = ref(false);
|
||||
const formModel = reactive({
|
||||
id: "",
|
||||
storeId: "",
|
||||
customerId: "",
|
||||
responsibleUserId: "",
|
||||
content: "",
|
||||
remindAtText: "",
|
||||
notifyChannelList: [] as FollowUpReminderNotifyChannel[]
|
||||
});
|
||||
const selectedCustomer = ref<Customer>();
|
||||
const selectedResponsible = ref<ManagedUser>();
|
||||
const photoItems = ref<PhotoItem[]>([]);
|
||||
const photoUrlList = computed(() => photoItems.value.map(item => item.previewUrl || item.url));
|
||||
const customerSelectorVisible = ref(false);
|
||||
const responsibleSelectorVisible = ref(false);
|
||||
const customerPickerStoreId = computed(() => formModel.storeId || currentStoreStore.currentStoreId);
|
||||
const responsiblePickerStoreId = computed(() => selectedCustomer.value?.storeId || customerPickerStoreId.value);
|
||||
const currentUserId = computed(() => userStore.loginUser.user?.id || userStore.loginUser.id || "");
|
||||
const selectedResponsibleName = computed(() => {
|
||||
if (!selectedResponsible.value) {
|
||||
return "请选择负责人";
|
||||
}
|
||||
if (selectedResponsible.value.userId === currentUserId.value) {
|
||||
return "本人";
|
||||
}
|
||||
return getResponsibleName(selectedResponsible.value);
|
||||
});
|
||||
|
||||
// ---------- 通知方式 ----------
|
||||
|
||||
const hasSmsChannel = computed(() => hasChannel("SMS"));
|
||||
const isTodayReminder = computed(() => {
|
||||
const remindAt = parseRemindAt();
|
||||
if (!remindAt) {
|
||||
return false;
|
||||
}
|
||||
return Time.formatDate(new Date(remindAt)) === Time.formatDate(new Date(Time.now()));
|
||||
});
|
||||
const isBeforeSmsCutoff = computed(() => {
|
||||
const now = new Date(Time.now());
|
||||
return now.getHours() < 8;
|
||||
});
|
||||
const canSelectSms = computed(() => isResponsiblePhoneValid(selectedResponsible.value)
|
||||
&& (!isTodayReminder.value || isBeforeSmsCutoff.value));
|
||||
const smsRuleText = computed(() => {
|
||||
if (!selectedResponsible.value) {
|
||||
return "短信通知要求负责人有有效的已验证手机号。";
|
||||
}
|
||||
if (!isResponsiblePhoneValid(selectedResponsible.value)) {
|
||||
return "当前负责人没有有效的已验证手机号,短信通知不可用。";
|
||||
}
|
||||
if (isTodayReminder.value && !isBeforeSmsCutoff.value) {
|
||||
return "今天 08:00 后创建今天的提醒不能选择短信通知。";
|
||||
}
|
||||
return "短信将在提醒日期 08:00 聚合发送,允许与站内通知同时选择。";
|
||||
});
|
||||
|
||||
function hasChannel(channel: FollowUpReminderNotifyChannel): boolean {
|
||||
return formModel.notifyChannelList.includes(channel);
|
||||
}
|
||||
|
||||
function setChannel(channel: FollowUpReminderNotifyChannel, checked: boolean): void {
|
||||
if (channel === "SMS" && checked && !canSelectSms.value) {
|
||||
Message.warning(smsRuleText.value);
|
||||
return;
|
||||
}
|
||||
const channelSet = new Set(formModel.notifyChannelList);
|
||||
if (checked) {
|
||||
channelSet.add(channel);
|
||||
} else {
|
||||
channelSet.delete(channel);
|
||||
}
|
||||
formModel.notifyChannelList = Array.from(channelSet);
|
||||
}
|
||||
|
||||
function isResponsiblePhoneValid(item?: ManagedUser): boolean {
|
||||
const phone = item?.user?.phoneNo;
|
||||
return Boolean(phone && item?.user?.phoneNoVerified && /^1\d{10}$/.test(phone));
|
||||
}
|
||||
|
||||
function getResponsibleName(item: ManagedUser): string {
|
||||
return item.user?.nick || item.user?.name || item.userId || "未命名负责人";
|
||||
}
|
||||
|
||||
// ---------- 客户和负责人 ----------
|
||||
|
||||
async function handleCustomerChange(customerId: string): Promise<void> {
|
||||
formModel.customerId = customerId;
|
||||
selectedCustomer.value = customerId ? await loadCustomer(customerId) : undefined;
|
||||
formModel.storeId = selectedCustomer.value?.storeId || currentStoreStore.currentStoreId;
|
||||
if (selectedResponsible.value && selectedResponsible.value.storeId !== formModel.storeId) {
|
||||
formModel.responsibleUserId = "";
|
||||
selectedResponsible.value = undefined;
|
||||
setChannel("SMS", false);
|
||||
}
|
||||
}
|
||||
|
||||
function handleResponsibleChange(item: ManagedUser): void {
|
||||
selectedResponsible.value = item;
|
||||
formModel.responsibleUserId = item.userId || "";
|
||||
if (isResponsiblePhoneValid(item) && canSelectSms.value) {
|
||||
setChannel("SMS", true);
|
||||
}
|
||||
}
|
||||
|
||||
function selectCurrentUser(): void {
|
||||
if (!currentUserId.value) {
|
||||
Message.warning("当前登录用户信息不可用");
|
||||
return;
|
||||
}
|
||||
handleResponsibleChange({
|
||||
storeId: responsiblePickerStoreId.value,
|
||||
userId: currentUserId.value,
|
||||
enabled: true,
|
||||
user: userStore.loginUser.user as Partial<User> | undefined
|
||||
});
|
||||
}
|
||||
|
||||
async function loadCustomer(customerId: string): Promise<Customer | undefined> {
|
||||
try {
|
||||
return await CustomerAPI.detail(customerId);
|
||||
} catch {
|
||||
Message.warning("客户详情加载失败");
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 时间 ----------
|
||||
|
||||
type RemindAtPreset = "tomorrow" | "afterTomorrow" | "custom";
|
||||
|
||||
const selectedRemindAtPreset = ref<RemindAtPreset>("tomorrow");
|
||||
const remindAtPickerVisible = ref(false);
|
||||
const remindAtDraftText = ref("");
|
||||
const minimumDateTimeText = computed(() => {
|
||||
const date = new Date(Time.now());
|
||||
date.setSeconds(0, 0);
|
||||
date.setMinutes(date.getMinutes() + 1);
|
||||
return Time.formatDateTime(date);
|
||||
});
|
||||
|
||||
function getQuickRemindAt(dayOffset: number): string {
|
||||
const date = new Date(Time.now());
|
||||
date.setSeconds(0, 0);
|
||||
date.setDate(date.getDate() + dayOffset);
|
||||
return Time.formatDateTime(date);
|
||||
}
|
||||
|
||||
function getQuickRemindDate(dayOffset: number): string {
|
||||
const date = new Date(Time.now());
|
||||
date.setDate(date.getDate() + dayOffset);
|
||||
return Time.formatDate(date);
|
||||
}
|
||||
|
||||
function getRemindAtPreset(value: string): RemindAtPreset {
|
||||
const remindAt = Time.toTimestamp(parseDateTime(value, false));
|
||||
if (!remindAt) {
|
||||
return "tomorrow";
|
||||
}
|
||||
const remindDate = Time.formatDate(new Date(remindAt));
|
||||
if (remindDate === getQuickRemindDate(1)) {
|
||||
return "tomorrow";
|
||||
}
|
||||
if (remindDate === getQuickRemindDate(2)) {
|
||||
return "afterTomorrow";
|
||||
}
|
||||
return "custom";
|
||||
}
|
||||
|
||||
function selectRemindAtPreset(preset: RemindAtPreset): void {
|
||||
selectedRemindAtPreset.value = preset;
|
||||
if (preset === "custom") {
|
||||
openRemindAtPicker();
|
||||
return;
|
||||
}
|
||||
formModel.remindAtText = getQuickRemindAt(preset === "tomorrow" ? 1 : 2);
|
||||
}
|
||||
|
||||
function handleRemindAtPresetChange(value: string | number | boolean): void {
|
||||
if (value !== "tomorrow" && value !== "afterTomorrow" && value !== "custom") {
|
||||
return;
|
||||
}
|
||||
selectRemindAtPreset(value);
|
||||
}
|
||||
|
||||
function openRemindAtPicker(): void {
|
||||
remindAtDraftText.value = formModel.remindAtText || minimumDateTimeText.value;
|
||||
remindAtPickerVisible.value = true;
|
||||
}
|
||||
|
||||
function cancelRemindAtPicker(): void {
|
||||
remindAtPickerVisible.value = false;
|
||||
selectedRemindAtPreset.value = getRemindAtPreset(formModel.remindAtText);
|
||||
}
|
||||
|
||||
function confirmRemindAt(value?: string | number): void {
|
||||
formModel.remindAtText = String(value || remindAtDraftText.value);
|
||||
selectedRemindAtPreset.value = "custom";
|
||||
remindAtPickerVisible.value = false;
|
||||
}
|
||||
|
||||
function parseRemindAt(): number | undefined {
|
||||
if (!formModel.remindAtText) {
|
||||
return undefined;
|
||||
}
|
||||
return Time.toTimestamp(parseDateTime(formModel.remindAtText, false));
|
||||
}
|
||||
|
||||
// ---------- 附件 ----------
|
||||
|
||||
const isUploading = ref(false);
|
||||
|
||||
async function uploadReminderPhotoList(fileList: File[]): Promise<PhotoItem[]> {
|
||||
isUploading.value = true;
|
||||
try {
|
||||
const tempFileList = await AttachmentAPI.upload(await compressUploadImageList(fileList));
|
||||
return tempFileList.flatMap((item, index) => {
|
||||
if (!item.id) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
attachment: {
|
||||
tempFileId: item.id,
|
||||
mimeType: fileList[index]?.type,
|
||||
name: fileList[index]?.name,
|
||||
title: fileList[index] ? getFileTitle(fileList[index].name) : undefined
|
||||
},
|
||||
tempFileId: item.id,
|
||||
attachType: "PHOTO",
|
||||
mimeType: fileList[index]?.type,
|
||||
url: AttachmentAPI.getTempReadURL(item.id || "")
|
||||
}
|
||||
];
|
||||
});
|
||||
} catch (error) {
|
||||
Message.error(getErrorMessage(error, "附件上传失败"));
|
||||
return [];
|
||||
} finally {
|
||||
isUploading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function getFileTitle(name: string): string {
|
||||
return name.replace(/\.[^.]+$/, "");
|
||||
}
|
||||
|
||||
function getAttachmentURL(item: FollowUpReminderAttachment): string {
|
||||
if (item.id) {
|
||||
return getAttachmentReadURL(item.id);
|
||||
}
|
||||
if (item.tempFileId) {
|
||||
return AttachmentAPI.getTempReadURL(item.tempFileId);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function toPhotoItems(items: readonly FollowUpReminderAttachment[]): PhotoItem[] {
|
||||
const result: PhotoItem[] = [];
|
||||
for (const item of items) {
|
||||
const url = getAttachmentURL(item);
|
||||
if (!url) {
|
||||
continue;
|
||||
}
|
||||
result.push({
|
||||
attachment: item,
|
||||
tempFileId: item.tempFileId,
|
||||
attachType: item.attachType || "PHOTO",
|
||||
url
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function toAttachmentList(items: readonly PhotoItem[]): FollowUpReminderAttachment[] {
|
||||
return items.map(item => ({
|
||||
...(item.attachment || {}),
|
||||
tempFileId: item.tempFileId || item.attachment?.tempFileId,
|
||||
attachType: item.attachType || item.attachment?.attachType || "PHOTO"
|
||||
})).filter(item => !!item.id || !!item.tempFileId);
|
||||
}
|
||||
|
||||
// ---------- 加载和保存 ----------
|
||||
|
||||
async function loadStoreScope(): Promise<void> {
|
||||
if (userStore.hasRoles(gaoRoleCodes.globalManager)) {
|
||||
await currentStoreStore.loadStoreList();
|
||||
formModel.storeId = currentStoreStore.currentStoreId;
|
||||
return;
|
||||
}
|
||||
const store = await currentStoreStore.loadLoginStore();
|
||||
formModel.storeId = store?.id || "";
|
||||
}
|
||||
|
||||
async function loadForm(): Promise<void> {
|
||||
await loadStoreScope();
|
||||
if (!routeId.value) {
|
||||
formModel.notifyChannelList = ["INTERNAL"];
|
||||
const queryCustomerId = String(route.query.customerId || "");
|
||||
if (queryCustomerId) {
|
||||
await handleCustomerChange(queryCustomerId);
|
||||
}
|
||||
selectCurrentUser();
|
||||
formModel.remindAtText = getQuickRemindAt(1);
|
||||
selectedRemindAtPreset.value = "tomorrow";
|
||||
return;
|
||||
}
|
||||
|
||||
const current = await FollowUpReminderAPI.detail(routeId.value);
|
||||
if (current.status !== "PENDING") {
|
||||
Message.warning("已完成的跟进提醒不能修改");
|
||||
await router.replace({ name: "CustomerFollowUpReminderDetail", params: { id: routeId.value } });
|
||||
return;
|
||||
}
|
||||
applyReminder(current);
|
||||
}
|
||||
|
||||
function applyReminder(current: FollowUpReminder): void {
|
||||
Object.assign(formModel, {
|
||||
id: current.id || "",
|
||||
storeId: current.storeId || "",
|
||||
customerId: current.customerId || "",
|
||||
responsibleUserId: current.responsibleUserId || "",
|
||||
content: current.content || "",
|
||||
remindAtText: current.remindAt ? Time.formatDateTime(new Date(current.remindAt)) : minimumDateTimeText.value,
|
||||
notifyChannelList: current.notifyChannelList || buildChannelList(current)
|
||||
});
|
||||
selectedCustomer.value = current.customer;
|
||||
selectedResponsible.value = current.responsibleUserId
|
||||
? {
|
||||
storeId: current.storeId,
|
||||
userId: current.responsibleUserId,
|
||||
enabled: true,
|
||||
user: current.responsibleUser as Partial<User> | undefined
|
||||
}
|
||||
: undefined;
|
||||
photoItems.value = toPhotoItems(current.attachmentList || []);
|
||||
selectedRemindAtPreset.value = getRemindAtPreset(formModel.remindAtText);
|
||||
}
|
||||
|
||||
function buildChannelList(item: FollowUpReminder): FollowUpReminderNotifyChannel[] {
|
||||
const result: FollowUpReminderNotifyChannel[] = [];
|
||||
if (item.internalNotifyEnabled) {
|
||||
result.push("INTERNAL");
|
||||
}
|
||||
if (item.smsNotifyEnabled) {
|
||||
result.push("SMS");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function validateForm(remindAt?: number): boolean {
|
||||
if (!formModel.customerId || !selectedCustomer.value?.id) {
|
||||
Message.warning("请选择客户");
|
||||
return false;
|
||||
}
|
||||
if (!formModel.responsibleUserId || !selectedResponsible.value?.userId) {
|
||||
Message.warning("请选择负责人");
|
||||
return false;
|
||||
}
|
||||
if (!formModel.content.trim()) {
|
||||
Message.warning("请填写跟进内容");
|
||||
return false;
|
||||
}
|
||||
if (!remindAt || !(0 === remindAt % 60000) || !(Time.now() < remindAt)) {
|
||||
Message.warning("请选择晚于当前时间的分钟提醒时间");
|
||||
return false;
|
||||
}
|
||||
if (hasSmsChannel.value && !canSelectSms.value) {
|
||||
Message.warning(smsRuleText.value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function save(): Promise<void> {
|
||||
if (isSaving.value || isUploading.value) {
|
||||
return;
|
||||
}
|
||||
const remindAt = parseRemindAt();
|
||||
if (!validateForm(remindAt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const payload: FollowUpReminderPayload = {
|
||||
id: formModel.id || undefined,
|
||||
storeId: formModel.storeId || undefined,
|
||||
customerId: formModel.customerId,
|
||||
responsibleUserId: formModel.responsibleUserId,
|
||||
content: formModel.content.trim(),
|
||||
remindAt: remindAt as number,
|
||||
notifyChannelList: [...formModel.notifyChannelList],
|
||||
attachmentList: toAttachmentList(photoItems.value)
|
||||
};
|
||||
|
||||
isSaving.value = true;
|
||||
try {
|
||||
let id = formModel.id;
|
||||
if (isEditMode.value) {
|
||||
await FollowUpReminderAPI.update(payload);
|
||||
} else {
|
||||
id = await FollowUpReminderAPI.create(payload);
|
||||
}
|
||||
Message.success("跟进提醒已保存");
|
||||
await router.replace({ name: "CustomerFollowUpReminderDetail", params: { id } });
|
||||
} catch (error) {
|
||||
Message.error(getErrorMessage(error, "跟进提醒保存失败"));
|
||||
} finally {
|
||||
isSaving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
navBarStore.setRightText(isEditMode.value ? "保存" : "提交", "var(--td-brand-color)", save);
|
||||
try {
|
||||
await loadForm();
|
||||
} catch (error) {
|
||||
Message.error(getErrorMessage(error, "跟进提醒加载失败"));
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => navBarStore.clearRight());
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.follow-up-reminder-edit {
|
||||
gap: 1rem;
|
||||
display: flex;
|
||||
padding: calc(var(--app-nav-height) + 1rem) 0 4rem;
|
||||
flex-direction: column;
|
||||
|
||||
.form {
|
||||
border-radius: 1rem;
|
||||
|
||||
.customer-picker {
|
||||
gap: .5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.customer-profile {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.responsible-picker {
|
||||
gap: .5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.remind-at {
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: var(--td-error-color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin: 0 2rem;
|
||||
font-size: .875rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
:global(html.theme-dark) {
|
||||
.follow-up-reminder-edit {
|
||||
.form {
|
||||
.picker-text {
|
||||
color: #e2e8f0;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
background: rgba(15, 23, 42, .72);
|
||||
border-color: rgba(148, 163, 184, .16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user