| | |
| | | :body-style="{ paddingBottom: '80px' }" |
| | | :footer-style="{ textAlign: 'right' }" |
| | | @after-open-change="afterOpenChange" |
| | | @close="close" |
| | | @close="drawerClose" |
| | | > |
| | | <template #title> |
| | | <pageHeadLeft :checked="true"></pageHeadLeft> |
| | | <pageHeadLeft |
| | | :checked="true" |
| | | :selectAllRow="[{ docCode }]" |
| | | @nextNum="drawerClose" |
| | | ></pageHeadLeft> |
| | | </template> |
| | | <template #extra> |
| | | <div style="font-size: 16px"> |
| | | 共<span class="m-1">222</span>封 |
| | | <LeftOutlined style="padding: 0 20px" /> |
| | | <RightOutlined /> |
| | | 共<span class="m-1">{{ props.allList.length }}</span |
| | | >封 |
| | | <LeftOutlined style="padding: 0 20px" @click="fnPrev" /> |
| | | <RightOutlined @click="fnNext" /> |
| | | </div> |
| | | </template> |
| | | <template #footer> |
| | | <div style="display: flex;"> |
| | | <a-textarea autoSize size="large" v-model:value="userName" placeholder="快速回复"> |
| | | <template #prefix> |
| | | <RollbackOutlined style="color: #999;" /> |
| | | </template> |
| | | </a-textarea> |
| | | <a-button size="large" type="primary" style="margin-left: 10px;">发送 |
| | | </a-button> |
| | | <div style="display: flex"> |
| | | <a-textarea autoSize size="large" v-model:value="content" placeholder="快速回复"> |
| | | <template #prefix> |
| | | <RollbackOutlined style="color: #999" /> |
| | | </template> |
| | | </a-textarea> |
| | | <a-button size="large" type="primary" style="margin-left: 10px" @click="fnQuickReply" |
| | | >发送 |
| | | </a-button> |
| | | </div> |
| | | </template> |
| | | <div |
| | |
| | | background: #fff; |
| | | " |
| | | > |
| | | <div class="title" style="margin-bottom: 20px;"> |
| | | <div class="title" style="margin-bottom: 20px"> |
| | | <div class="left"> |
| | | <span style="margin-right: 20px; font-size: 24px; font-weight: 700"> |
| | | <a-tooltip placement="bottom"> |
| | |
| | | </span> |
| | | </div> |
| | | <div class="right"> |
| | | <div class="tate">{{ tableRowData.receiveTime }}</div> |
| | | <div class="tate">{{ formatToDateDay(tableRowData.receiveTime) }}</div> |
| | | <div> |
| | | <a-dropdown-button> |
| | | <span> |
| | |
| | | <div class="flex-between"> |
| | | <div class="ct-left p-2" :class="isOpen ? 'isOpen' : 'onOpen'"> |
| | | <div class="user p-1"> |
| | | <div style="display: flex; align-items: center;"> |
| | | <div style="display: flex; align-items: center"> |
| | | <a-avatar size="small" style="margin-right: 8px" src="#" /> |
| | | {{ tableRowData.sender }} |
| | | <span>{{ `<${tableRowData.sender}>` }}</span> |
| | | <span style="margin: 0 10px;">发送</span> |
| | | <span style="margin: 0 10px">发送</span> |
| | | <a-popover placement="bottom"> |
| | | <template #content> |
| | | <div |
| | |
| | | " |
| | | > |
| | | <a-avatar size="small" style="margin-right: 8px" src="#" /> |
| | | <span style="color: #000; font-weight: 700"> {{ `${tableRowData.receiver}` }}</span> |
| | | <span style="color: #000; font-weight: 700"> |
| | | {{ `${tableRowData.receiver}` }}</span |
| | | > |
| | | <CopyOutlined /> |
| | | </div> |
| | | <div class="display-flex p-2"> |
| | |
| | | <div |
| | | type="info" |
| | | class="p-2" |
| | | style=" |
| | | margin-top: 10px; |
| | | background-color: #e4f1ff; |
| | | font-size: 14px; |
| | | " |
| | | style="margin-top: 10px; background-color: #e4f1ff; font-size: 14px" |
| | | > |
| | | <span>{{ `<${tableRowData.sender}>` }}</span> |
| | | <span>暂未查询到该客户的当地时间</span> |
| | | <!-- <span>2024-06-08 22:22</span> --> |
| | | <span>暂未查询到该客户的当地时间</span> |
| | | <!-- <span>2024-06-08 22:22</span> --> |
| | | </div> |
| | | <div class="ct" v-if="tableRowData.content"> |
| | | <TinymcePw v-model="tableRowData.content" /> |
| | | <TinymcePw ref="TinymcePwRef" v-model="tableRowData.content" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | </template> |
| | | |
| | | <script lang="ts" setup> |
| | | name: 'drawerDetail'; |
| | | name: 'drawerDetail'; |
| | | |
| | | import { ref, watch, defineProps, defineEmits, computed, h } from 'vue'; |
| | | import { |
| | | LeftOutlined, |
| | | RightOutlined, |
| | | DoubleLeftOutlined, |
| | | PushpinOutlined, |
| | | CopyOutlined, |
| | | UserOutlined, |
| | | RollbackOutlined |
| | | } from '@ant-design/icons-vue'; |
| | | import pageHeadLeft from './pageHeadLeft.vue'; |
| | | import { TinymcePw } from '@/components/Tinymce'; |
| | | import { getMailInfoApi } from '@/api/email/userList'; |
| | | import { useCollapseStore } from '@/store/modules/useCollapseStore'; |
| | | import { ref, watch, defineProps, defineEmits, computed } from 'vue'; |
| | | import { |
| | | LeftOutlined, |
| | | RightOutlined, |
| | | DoubleLeftOutlined, |
| | | PushpinOutlined, |
| | | CopyOutlined, |
| | | UserOutlined, |
| | | RollbackOutlined, |
| | | } from '@ant-design/icons-vue'; |
| | | import pageHeadLeft from './pageHeadLeft.vue'; |
| | | import { TinymcePw } from '@/components/Tinymce'; |
| | | import { getMailInfoApi, setQuickReplyAPi } from '@/api/email/userList'; |
| | | import { useCollapseStore } from '@/store/modules/useCollapseStore'; |
| | | import { nextTick } from 'vue'; |
| | | import { formatToDateDay } from '@/utils/dateUtil'; |
| | | import { useLoading } from '@/components/Loading'; |
| | | |
| | | // 定义属性 |
| | | interface Props { |
| | | modelValue: boolean; |
| | | title?: string; |
| | | placement?: 'left' | 'right' | 'top' | 'bottom'; |
| | | idName?: string; |
| | | selectIds?: number[]; |
| | | mailId?: string; |
| | | allList; |
| | | } |
| | | // const [open, close, setTip] = useLoading(); |
| | | // 定义属性 |
| | | interface Props { |
| | | modelValue: boolean; |
| | | title?: string; |
| | | placement?: 'left' | 'right' | 'top' | 'bottom'; |
| | | idName?: string; |
| | | selectIds?: number[]; |
| | | mailId?: string; |
| | | selectAllRow: Array<any>; |
| | | allList; |
| | | } |
| | | |
| | | const props = defineProps<Props>(); |
| | | const tableRowData = ref<Record<string, any>>({}); |
| | | const emit = defineEmits(['update:modelValue', 'updateData']); |
| | | const drawerOpen = ref(props.modelValue); |
| | | const props = defineProps<Props>(); |
| | | |
| | | // 监听属性变化 |
| | | watch(() => props.modelValue, (newValue) => { |
| | | drawerOpen.value = newValue; |
| | | console.log(newValue, '---------4'); |
| | | if (newValue) { |
| | | getMailInfoApi({ docCode: props.mailId }).then((res) => { |
| | | tableRowData.value = res.data; |
| | | const tableRowData = ref<Record<string, any>>({}); |
| | | const emit = defineEmits(['update:modelValue', 'updateData']); |
| | | const drawerOpen = ref(props.modelValue); |
| | | const TinymcePwRef = ref(); |
| | | const docCode = ref(props.mailId); |
| | | watch( |
| | | () => props.mailId, |
| | | (newVal) => { |
| | | docCode.value = newVal; |
| | | }, |
| | | ); |
| | | // 监听属性变化 |
| | | watch( |
| | | () => props.modelValue, |
| | | (newValue) => { |
| | | drawerOpen.value = newValue; |
| | | nextTick(() => { |
| | | console.log(newValue, '---------4', TinymcePwRef.value); |
| | | }); |
| | | if (newValue) { |
| | | fnGetMailInfo(props.mailId); |
| | | } |
| | | }, |
| | | ); |
| | | |
| | | function fnGetMailInfo(id) { |
| | | getMailInfoApi({ docCode: id }) |
| | | .then((res) => { |
| | | docCode.value = id; |
| | | tableRowData.value = res.data; |
| | | }) |
| | | .catch(() => {}); |
| | | } |
| | | // 更新外部属性 |
| | | watch(drawerOpen, (newValue) => { |
| | | emit('update:modelValue', newValue); |
| | | }); |
| | | |
| | | // 方法 |
| | | const collapseStore = useCollapseStore(); |
| | | const afterOpenChange = (bool: boolean) => { |
| | | if (bool) { |
| | | fnGetUserList({ page: 1, pageSize: 30 }); |
| | | } |
| | | collapseStore.toggle(false); |
| | | }; |
| | | const drawerClose = (e) => { |
| | | drawerOpen.value = false; |
| | | }; |
| | | |
| | | function truncateString(str, maxLength) { |
| | | return str.length > maxLength ? str.substring(0, maxLength) + '...' : str; |
| | | } |
| | | |
| | | const fnGetUserList = (params) => { |
| | | // 调用接口逻辑 |
| | | }; |
| | | |
| | | // 计算属性 |
| | | const placement = computed(() => props.placement || 'right'); |
| | | |
| | | // 抽屉开关 |
| | | const fnSaveOpenChange = () => { |
| | | // 抽屉保存逻辑 |
| | | }; |
| | | |
| | | const content = ref(''); |
| | | const isOpen = ref(false); |
| | | |
| | | function fuToggleContent() { |
| | | isOpen.value = !isOpen.value; |
| | | } |
| | | |
| | | function fnPrev() { |
| | | const id = getPrevId(props.allList, docCode.value); |
| | | fnGetMailInfo(id); |
| | | } |
| | | function fnNext() { |
| | | const id = getNextId(props.allList, docCode.value); |
| | | fnGetMailInfo(id); |
| | | } |
| | | function getNextId(list, id) { |
| | | const index = list.findIndex((item) => item.docCode === id); |
| | | if (index < list.length - 1) { |
| | | return list[index + 1].docCode; |
| | | } else { |
| | | return list[0].docCode; |
| | | } |
| | | } |
| | | function getPrevId(list, id) { |
| | | const index = list.findIndex((item) => item.docCode === id); |
| | | if (index > 0) { |
| | | return list[index - 1].docCode; |
| | | } else { |
| | | return list[list.length - 1].docCode; |
| | | } |
| | | } |
| | | |
| | | import { useMessage } from '@/hooks/web/useMessage'; |
| | | |
| | | const { createMessage } = useMessage(); |
| | | function fnQuickReply() { |
| | | if (!content.value) { |
| | | createMessage.warning('请输入回复内容'); |
| | | return; |
| | | } |
| | | const data = { |
| | | docCode: docCode.value, |
| | | content: content.value, |
| | | }; |
| | | setQuickReplyAPi(data).then((res) => { |
| | | if (res.code == 0) { |
| | | createMessage.success(res.msg); |
| | | |
| | | fnGetMailInfo(props.mailId); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // 更新外部属性 |
| | | watch(drawerOpen, (newValue) => { |
| | | emit('update:modelValue', newValue); |
| | | }); |
| | | |
| | | // 方法 |
| | | const collapseStore = useCollapseStore(); |
| | | const afterOpenChange = (bool: boolean) => { |
| | | if (bool) { |
| | | fnGetUserList({ page: 1, pageSize: 30 }); |
| | | } |
| | | collapseStore.toggle(false); |
| | | }; |
| | | const close = (e) => { |
| | | drawerOpen.value = false; |
| | | }; |
| | | |
| | | function truncateString(str, maxLength) { |
| | | return str.length > maxLength ? str.substring(0, maxLength) + '...' : str; |
| | | } |
| | | |
| | | const fnGetUserList = (params) => { |
| | | // 调用接口逻辑 |
| | | }; |
| | | |
| | | // 计算属性 |
| | | const title = computed(() => props.title || 'Basic Drawer'); |
| | | const placement = computed(() => props.placement || 'right'); |
| | | const idName = computed(() => props.idName || 'recipients'); |
| | | |
| | | // 抽屉开关 |
| | | const fnSaveOpenChange = () => { |
| | | // 抽屉保存逻辑 |
| | | }; |
| | | |
| | | const userName = ref(''); |
| | | const isOpen = ref(false); |
| | | |
| | | function fuToggleContent() { |
| | | isOpen.value = !isOpen.value; |
| | | } |
| | | </script> |
| | | |
| | | <style scoped lang="less"> |
| | | .table-content { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | border-top: 1px solid #f0f0f0; |
| | | |
| | | .left { |
| | | width: 80%; |
| | | height: 100%; |
| | | border-right: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .right { |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | ::v-deep(.ant-table) { |
| | | min-height: 355px !important; |
| | | } |
| | | |
| | | .title { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | |
| | | & .left { |
| | | .table-content { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 50%; |
| | | justify-content: space-between; |
| | | border-top: 1px solid #f0f0f0; |
| | | |
| | | .left { |
| | | width: 80%; |
| | | height: 100%; |
| | | border-right: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .right { |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | & .right { |
| | | ::v-deep(.ant-table) { |
| | | min-height: 355px !important; |
| | | } |
| | | |
| | | .title { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 25%; |
| | | |
| | | & .tate { |
| | | color: #999; |
| | | font-size: 14px; |
| | | & .left { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 50%; |
| | | } |
| | | |
| | | & .right { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | width: 25%; |
| | | |
| | | & .tate { |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .ct { |
| | | margin: 20px 0; |
| | | } |
| | | .ct { |
| | | margin: 20px 0; |
| | | } |
| | | |
| | | .flex-between { |
| | | display: flex; |
| | | margin-top: 4%; |
| | | } |
| | | .flex-between { |
| | | display: flex; |
| | | margin-top: 4%; |
| | | } |
| | | |
| | | .ct-left { |
| | | padding-right: 20px; |
| | | } |
| | | .ct-left { |
| | | padding-right: 20px; |
| | | } |
| | | |
| | | .ct-right { |
| | | border-left: 1px solid #f0f0f0; |
| | | } |
| | | .ct-right { |
| | | border-left: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | .toggle-btn { |
| | | display: flex; |
| | | position: absolute; |
| | | z-index: 99; |
| | | top: 50%; |
| | | width: 20px; |
| | | height: 54px; |
| | | padding-left: 5px; |
| | | transform: translateY(-50%); |
| | | border: 1px solid #f0f0f0; |
| | | border-right: none; |
| | | border-radius: 10px 0 0 10px; |
| | | background: #fafafa; |
| | | } |
| | | .toggle-btn { |
| | | display: flex; |
| | | position: absolute; |
| | | z-index: 99; |
| | | top: 50%; |
| | | width: 20px; |
| | | height: 54px; |
| | | padding-left: 5px; |
| | | transform: translateY(-50%); |
| | | border: 1px solid #f0f0f0; |
| | | border-right: none; |
| | | border-radius: 10px 0 0 10px; |
| | | background: #fafafa; |
| | | } |
| | | |
| | | .onOpen { |
| | | width: 100%; |
| | | } |
| | | .onOpen { |
| | | width: 100%; |
| | | } |
| | | |
| | | .isOpen { |
| | | width: 69%; |
| | | } |
| | | .isOpen { |
| | | width: 69%; |
| | | } |
| | | |
| | | .iconOpen { |
| | | right: 0%; |
| | | } |
| | | .iconOpen { |
| | | right: 0%; |
| | | } |
| | | |
| | | .onIconOpen { |
| | | right: 32%; |
| | | } |
| | | .onIconOpen { |
| | | right: 32%; |
| | | } |
| | | </style> |