Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
frontend-yd-email
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Sweet Zhang
frontend-yd-email
Commits
69e37e36
Commit
69e37e36
authored
Sep 30, 2025
by
Sweet Zhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
搜索框增加模糊搜索
parent
cde5c983
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
116 additions
and
31 deletions
+116
-31
src/views/ComposeEmail.vue
+86
-22
src/views/ContactSelector.vue
+7
-1
src/views/EmailManagement.vue
+2
-2
src/views/SenderManagement.vue
+21
-6
No files found.
src/views/ComposeEmail.vue
View file @
69e37e36
...
@@ -2,32 +2,53 @@
...
@@ -2,32 +2,53 @@
<div
class=
"bg-white rounded-lg shadow-md p-6"
v-loading=
"loading"
>
<div
class=
"bg-white rounded-lg shadow-md p-6"
v-loading=
"loading"
>
<div
class=
"mb-4"
>
<div
class=
"mb-4"
>
<label
class=
"block text-gray-700 mb-2 font-medium"
>
发件人
</label>
<label
class=
"block text-gray-700 mb-2 font-medium"
>
发件人
</label>
<select
<
el-
select
v-model=
"currentSender"
v-model=
"currentSender"
class=
"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
value-key=
"senderBizId"
filterable
remote
reserve-keyword
placeholder=
"请输入发件人姓名或邮箱搜索"
:remote-method=
"(query) => remoteSearch(query, 'senders')"
:loading=
"loading"
size=
"large"
class=
"w-full"
>
>
<option
v-for=
"sender in senders"
:key=
"sender.senderBizId"
:value=
"sender"
>
<el-option
{{
sender
.
email
}}
- 发件人姓名:
{{
sender
.
displayName
}}
v-for=
"sender in senders"
</option>
:key=
"sender.senderBizId"
</select>
:label=
"sender.email"
:value=
"sender"
/>
</el-select>
</div>
</div>
<div
class=
"mb-4"
>
<div
class=
"mb-4"
>
<label
class=
"block text-gray-700 mb-2 font-medium"
>
变量模板
</label>
<label
class=
"block text-gray-700 mb-2 font-medium"
>
变量模板
</label>
<div
class=
"flex flex-col sm:flex-row gap-2"
>
<div
class=
"flex flex-col sm:flex-row gap-2"
>
<select
<
el-
select
v-model=
"selectedVariableTemplate"
v-model=
"selectedVariableTemplate"
class=
"flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
value-key=
"variableGroupBizId"
@
change=
"applyVariableTemplate"
filterable
remote
reserve-keyword
placeholder=
"选择模板"
:remote-method=
"(query) => remoteSearch(query, 'groups')"
:loading=
"loading"
size=
"large"
class=
"flex-auto"
>
>
<option
value=
""
>
-- 选择模板 --
</option>
<el-option
value=
""
>
-- 选择模板 --
</el-option>
<option
v-for=
"template in groups"
:key=
"template.variableGroupBizId"
:value=
"template"
>
<el-option
{{
template
.
groupName
}}
v-for=
"template in groups"
</option>
:key=
"template.variableGroupBizId"
</select>
:value=
"template"
:label=
"template.groupName"
/>
</el-select>
<!-- 当选择模版有值时,显示导入数据按钮 -->
<!-- 当选择模版有值时,显示导入数据按钮 -->
<button
<button
@
click=
"((showImportContacts = true), (importSource = 1))"
@
click=
"((showImportContacts = true), (importSource = 1))"
class=
"bg-blue-50 hover:bg-blue-100 text-blue-600 px-4 py-2 rounded-md border border-blue-200 transition-colors flex items-center"
class=
"bg-blue-50 hover:bg-blue-100 text-blue-600 px-4 py-2 rounded-md border border-blue-200 transition-colors flex
-none
items-center"
v-if=
"selectedVariableTemplate"
v-if=
"selectedVariableTemplate"
>
>
<i
class=
"fas fa-address-book mr-1"
></i>
导入数据
<i
class=
"fas fa-address-book mr-1"
></i>
导入数据
...
@@ -212,6 +233,7 @@
...
@@ -212,6 +233,7 @@
v-if=
"showContactSelector"
v-if=
"showContactSelector"
:contacts=
"contacts"
:contacts=
"contacts"
@
confirm-selection=
"confirmContactSelection"
@
confirm-selection=
"confirmContactSelection"
@
query-change=
"remoteSearch($event, 'contacts')"
@
close=
"showContactSelector = false"
@
close=
"showContactSelector = false"
/>
/>
...
@@ -244,7 +266,7 @@ import { useRouter } from 'vue-router'
...
@@ -244,7 +266,7 @@ import { useRouter } from 'vue-router'
const
router
=
useRouter
()
const
router
=
useRouter
()
const
navigateToEmailRecords
=
()
=>
{
const
navigateToEmailRecords
=
()
=>
{
router
.
push
({
name
:
'
EmailRecord
s'
})
router
.
push
({
name
:
'
email
s'
})
}
}
import
ContactSelector
from
'./ContactSelector.vue'
import
ContactSelector
from
'./ContactSelector.vue'
import
VariableSelector
from
'./VariableSelector.vue'
import
VariableSelector
from
'./VariableSelector.vue'
...
@@ -264,6 +286,52 @@ const handleClose = (done: () => void) => {
...
@@ -264,6 +286,52 @@ const handleClose = (done: () => void) => {
// catch error
// catch error
})
})
}
}
// 远程搜索方法
const
remoteSearch
=
async
(
query
:
string
,
type
:
string
)
=>
{
console
.
log
(
query
,
type
)
if
(
query
)
{
loading
.
value
=
true
try
{
if
(
type
===
'senders'
)
{
const
res
=
await
senderApi
.
getEmailSenderConfigList
({
queryContent
:
query
,
pageNo
:
1
,
pageSize
:
100
,
})
senders
.
value
=
res
.
data
?.
records
||
[]
}
else
if
(
type
===
'groups'
)
{
const
res
=
await
variableGroupApi
.
getEmailVariableGroupList
({
queryContent
:
query
,
pageNo
:
1
,
pageSize
:
100
,
})
groups
.
value
=
res
.
data
?.
records
||
[]
}
else
if
(
type
===
'contacts'
)
{
const
res
=
await
contactApi
.
getContactList
({
queryContent
:
query
,
pageNo
:
1
,
pageSize
:
100
,
})
contacts
.
value
=
res
.
data
?.
records
||
[]
}
}
catch
(
error
)
{
console
.
error
(
'搜索失败:'
,
error
)
ElMessage
.
error
(
'搜索失败'
)
}
finally
{
loading
.
value
=
false
}
}
else
{
// 如果查询为空,重新加载默认选项
if
(
type
===
'contacts'
)
{
getContacts
()
}
else
if
(
type
===
'groups'
)
{
getGroups
()
}
else
if
(
type
===
'senders'
)
{
getSenders
()
}
}
}
// 初始化数据
// 初始化数据
const
getSenders
=
()
=>
{
const
getSenders
=
()
=>
{
senderApi
senderApi
...
@@ -301,9 +369,8 @@ const senders = ref<Sender[]>([])
...
@@ -301,9 +369,8 @@ const senders = ref<Sender[]>([])
const
contacts
=
ref
<
Contact
<
unknown
>
[]
>
([])
const
contacts
=
ref
<
Contact
<
unknown
>
[]
>
([])
const
groups
=
ref
<
VariableTemplate
[]
>
([])
const
groups
=
ref
<
VariableTemplate
[]
>
([])
const
variables
=
ref
<
Variable
[]
>
([])
const
variables
=
ref
<
Variable
[]
>
([])
const
currentSender
=
ref
()
// 状态
const
currentSender
=
ref
<
Sender
|
null
>
(
senders
.
value
.
length
>
0
?
senders
.
value
[
0
]
:
null
)
const
emailForm
=
ref
<
EmailForm
>
({
const
emailForm
=
ref
<
EmailForm
>
({
senderBizId
:
''
,
senderBizId
:
''
,
sendEmail
:
''
,
sendEmail
:
''
,
...
@@ -530,7 +597,6 @@ const getImportedContacts = (sessionId?: string, type?: string) => {
...
@@ -530,7 +597,6 @@ const getImportedContacts = (sessionId?: string, type?: string) => {
importRecords
.
value
=
res
.
data
.
records
||
[]
importRecords
.
value
=
res
.
data
.
records
||
[]
// 从导入记录中提取收件人和抄送人
// 从导入记录中提取收件人和抄送人
if
(
type
==
'update'
)
{
if
(
type
==
'update'
)
{
debugger
emailForm
.
value
.
receiveEmail
=
importRecords
.
value
emailForm
.
value
.
receiveEmail
=
importRecords
.
value
.
map
((
item
)
=>
item
.
receiveEmail
)
.
map
((
item
)
=>
item
.
receiveEmail
)
.
join
(
','
)
.
join
(
','
)
...
@@ -547,8 +613,6 @@ const getImportedContacts = (sessionId?: string, type?: string) => {
...
@@ -547,8 +613,6 @@ const getImportedContacts = (sessionId?: string, type?: string) => {
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
import
FileUploadComponent
from
'@/components/FileUploadComponent.vue'
import
FileUploadComponent
from
'@/components/FileUploadComponent.vue'
import
{
UploadResult
}
from
'@/utils/fileUpload'
import
{
UploadResult
}
from
'@/utils/fileUpload'
import
{
get
}
from
'http'
import
{
ca
,
lo
}
from
'element-plus/es/locales.mjs'
// 上传成功的文件
// 上传成功的文件
const
uploadedFiles
=
ref
<
any
[]
>
([])
const
uploadedFiles
=
ref
<
any
[]
>
([])
...
@@ -581,7 +645,7 @@ const sendSelfEmail = () => {
...
@@ -581,7 +645,7 @@ const sendSelfEmail = () => {
type
:
'success'
,
type
:
'success'
,
})
})
}
else
{
}
else
{
ElMessage
.
error
(
'测试邮件发送失败'
)
ElMessage
.
error
(
`测试邮件发送失败:
${
res
.
data
.
msg
||
'未知错误'
}
`
)
}
}
})
})
}
}
...
...
src/views/ContactSelector.vue
View file @
69e37e36
...
@@ -14,6 +14,7 @@
...
@@ -14,6 +14,7 @@
type=
"text"
type=
"text"
class=
"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
class=
"w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder=
"搜索联系人..."
placeholder=
"搜索联系人..."
@
change=
"handleQueryChange"
/>
/>
</div>
</div>
<div
class=
"space-y-2"
>
<div
class=
"space-y-2"
>
...
@@ -69,7 +70,7 @@ const props = defineProps({
...
@@ -69,7 +70,7 @@ const props = defineProps({
},
},
})
})
const
emits
=
defineEmits
([
'confirm-selection'
,
'close'
])
const
emits
=
defineEmits
([
'confirm-selection'
,
'close'
,
'query-change'
])
// 状态
// 状态
const
searchTerm
=
ref
(
''
)
const
searchTerm
=
ref
(
''
)
...
@@ -85,6 +86,11 @@ const filteredContacts = computed(() => {
...
@@ -85,6 +86,11 @@ const filteredContacts = computed(() => {
)
)
})
})
const
handleQueryChange
=
()
=>
{
searchTerm
.
value
=
searchTerm
.
value
.
trim
()
emits
(
'query-change'
,
searchTerm
.
value
)
}
// 方法
// 方法
const
toggleSelection
=
(
contact
:
Contact
)
=>
{
const
toggleSelection
=
(
contact
:
Contact
)
=>
{
const
index
=
selectedContacts
.
value
.
indexOf
(
contact
.
contactBizId
||
''
)
const
index
=
selectedContacts
.
value
.
indexOf
(
contact
.
contactBizId
||
''
)
...
...
src/views/EmailManagement.vue
View file @
69e37e36
...
@@ -116,9 +116,9 @@
...
@@ -116,9 +116,9 @@
>
>
查看
查看
</button>
</button>
<button
@
click=
"reuseEmailContent(email)"
class=
"text-green-600 hover:text-green-900"
>
<
!--
<
button
@
click=
"reuseEmailContent(email)"
class=
"text-green-600 hover:text-green-900"
>
复用
复用
</button>
</button>
-->
</td>
</td>
</tr>
</tr>
</tbody>
</tbody>
...
...
src/views/SenderManagement.vue
View file @
69e37e36
...
@@ -55,7 +55,6 @@
...
@@ -55,7 +55,6 @@
<button
<button
@
click=
"saveSender"
@
click=
"saveSender"
class=
"px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-700 transition-colors"
class=
"px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-700 transition-colors"
:disabled=
"!formData.email || !formData.password || !formData.providerBizId"
>
>
{{
editingSenderId
?
'更新发件人'
:
'添加发件人'
}}
{{
editingSenderId
?
'更新发件人'
:
'添加发件人'
}}
</button>
</button>
...
@@ -201,6 +200,7 @@ import { emailProviderApi, senderApi, getEmailSenderConfigList } from '@/api/api
...
@@ -201,6 +200,7 @@ import { emailProviderApi, senderApi, getEmailSenderConfigList } from '@/api/api
import
type
{
Sender
}
from
'@/types/index'
import
type
{
Sender
}
from
'@/types/index'
// 引入分页组件
// 引入分页组件
import
Pagination
from
'@/components/Pagination.vue'
import
Pagination
from
'@/components/Pagination.vue'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
// 初始数据
// 初始数据
const
total
=
ref
(
0
)
const
total
=
ref
(
0
)
...
@@ -236,7 +236,7 @@ const handlePageSizeUpdate = (size: number) => {
...
@@ -236,7 +236,7 @@ const handlePageSizeUpdate = (size: number) => {
}
}
// 引入弹窗组件
// 引入弹窗组件
import
CommonModal
from
'@/components/CommonModal.vue'
import
CommonModal
from
'@/components/CommonModal.vue'
import
{
get
}
from
'http
'
import
type
{
Action
}
from
'element-plus
'
// 弹窗提示信息对象
// 弹窗提示信息对象
const
modalVisible
=
ref
(
false
)
const
modalVisible
=
ref
(
false
)
const
modalConfig
=
ref
({
const
modalConfig
=
ref
({
...
@@ -246,6 +246,24 @@ const modalConfig = ref({
...
@@ -246,6 +246,24 @@ const modalConfig = ref({
triggerKey
:
'templateModal'
,
triggerKey
:
'templateModal'
,
})
})
const
alertInfo
=
(
content
:
string
,
title
:
string
=
'提示'
,
type
:
'info'
|
'success'
|
'warning'
|
'error'
=
'info'
,
msg
:
string
=
''
,
)
=>
{
ElMessageBox
.
alert
(
content
,
title
,
{
type
:
type
,
confirmButtonText
:
'OK'
,
callback
:
(
action
:
Action
)
=>
{
// ElMessage({
// type: type,
// message: msg || '操作成功',
// })
},
})
}
const
openModal
=
(
const
openModal
=
(
config
:
{
triggerKey
?:
string
;
showCancel
?:
boolean
;
title
?:
string
;
message
?:
string
}
=
{},
config
:
{
triggerKey
?:
string
;
showCancel
?:
boolean
;
title
?:
string
;
message
?:
string
}
=
{},
)
=>
{
)
=>
{
...
@@ -337,10 +355,7 @@ const getSenders = () => {
...
@@ -337,10 +355,7 @@ const getSenders = () => {
const
saveSender
=
()
=>
{
const
saveSender
=
()
=>
{
console
.
log
(
formData
.
value
)
console
.
log
(
formData
.
value
)
if
(
!
formData
.
value
.
email
||
!
formData
.
value
.
password
||
!
formData
.
value
.
providerBizId
)
{
if
(
!
formData
.
value
.
email
||
!
formData
.
value
.
password
||
!
formData
.
value
.
providerBizId
)
{
openModal
({
alertInfo
(
'请填写完整邮箱授权码和服务商'
,
'添加失败'
,
'error'
)
title
:
'添加失败'
,
message
:
'请填写完整邮箱授权码和服务商'
,
})
return
return
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment