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
4de2993b
Commit
4de2993b
authored
Sep 25, 2025
by
Sweet Zhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
联系人管理、发件人管理对接
parent
d86fbaed
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
690 additions
and
458 deletions
+690
-458
src/App.vue
+1
-76
src/api/api.ts
+38
-19
src/router/index.ts
+1
-1
src/types/index.ts
+14
-13
src/utils/request.ts
+1
-1
src/views/ComposeEmail.vue
+16
-38
src/views/ContactManagement.vue
+430
-212
src/views/EmailManagement.vue
+2
-14
src/views/SenderManagement.vue
+184
-59
src/views/VariableManagement.vue
+3
-25
No files found.
src/App.vue
View file @
4de2993b
...
@@ -34,19 +34,7 @@
...
@@ -34,19 +34,7 @@
</header>
</header>
<!-- 使用router-view显示当前路由组件 -->
<!-- 使用router-view显示当前路由组件 -->
<router-view
<router-view
/>
:senders=
"senders"
:contacts=
"contacts"
:variables=
"variables"
:variable-templates=
"variableTemplates"
:emails=
"emails"
@
save-email=
"saveEmail"
@
update-contacts=
"updateContacts"
@
update-senders=
"updateSenders"
@
update-variables=
"updateVariables"
@
update-variable-templates=
"updateVariableTemplates"
@
reuse-email=
"reuseEmail"
/>
</main>
</main>
</div>
</div>
</div>
</div>
...
@@ -59,7 +47,6 @@ import { useRoute, useRouter } from 'vue-router'
...
@@ -59,7 +47,6 @@ import { useRoute, useRouter } from 'vue-router'
import
LoginPage
from
'./views/LoginPage.vue'
import
LoginPage
from
'./views/LoginPage.vue'
import
Sidebar
from
'./views/Sidebar.vue'
import
Sidebar
from
'./views/Sidebar.vue'
import
MobileSidebar
from
'./views/MobileSidebar.vue'
import
MobileSidebar
from
'./views/MobileSidebar.vue'
import
type
{
Contact
,
Sender
,
Variable
,
VariableTemplate
,
Email
}
from
'./types'
const
route
=
useRoute
()
const
route
=
useRoute
()
const
router
=
useRouter
()
const
router
=
useRouter
()
...
@@ -80,13 +67,6 @@ watch(
...
@@ -80,13 +67,6 @@ watch(
},
},
)
)
// 数据存储(保持不变)
const
contacts
=
ref
<
Contact
[]
>
([])
const
senders
=
ref
<
Sender
[]
>
([])
const
variables
=
ref
<
Variable
[]
>
([])
const
variableTemplates
=
ref
<
VariableTemplate
[]
>
([])
const
emails
=
ref
<
Email
[]
>
([])
// 页面标题映射(保持不变)
// 页面标题映射(保持不变)
const
pageTitles
=
{
const
pageTitles
=
{
compose
:
'写邮件'
,
compose
:
'写邮件'
,
...
@@ -100,7 +80,6 @@ const pageTitles = {
...
@@ -100,7 +80,6 @@ const pageTitles = {
const
handleLogin
=
()
=>
{
const
handleLogin
=
()
=>
{
isAuthenticated
.
value
=
true
isAuthenticated
.
value
=
true
isLoginPage
.
value
=
false
isLoginPage
.
value
=
false
loadInitialData
()
router
.
push
(
'/compose'
)
// 登录后跳转到写邮件页面
router
.
push
(
'/compose'
)
// 登录后跳转到写邮件页面
}
}
...
@@ -110,64 +89,10 @@ const handleLogout = () => {
...
@@ -110,64 +89,10 @@ const handleLogout = () => {
router
.
push
(
'/login'
)
// 退出后跳转到登录页面
router
.
push
(
'/login'
)
// 退出后跳转到登录页面
}
}
const
handlePageChange
=
(
page
:
string
)
=>
{
currentPage
.
value
=
page
as
'compose'
|
'contacts'
|
'senders'
|
'variables'
|
'emails'
}
const
handleMobilePageChange
=
(
page
:
string
)
=>
{
currentPage
.
value
=
page
as
'compose'
|
'contacts'
|
'senders'
|
'variables'
|
'emails'
showMobileMenu
.
value
=
false
}
const
updateContacts
=
(
newContacts
:
Contact
[])
=>
{
contacts
.
value
=
newContacts
}
const
updateSenders
=
(
newSenders
:
Sender
[])
=>
{
senders
.
value
=
newSenders
}
const
updateVariables
=
(
newVariables
:
Variable
[])
=>
{
variables
.
value
=
newVariables
}
const
updateVariableTemplates
=
(
newTemplates
:
VariableTemplate
[])
=>
{
variableTemplates
.
value
=
newTemplates
}
const
saveEmail
=
(
email
:
Email
)
=>
{
emails
.
value
.
push
(
email
)
}
const
reuseEmail
=
(
emailData
:
Email
)
=>
{
currentPage
.
value
=
'compose'
// 这里可以传递需要复用的邮件数据到ComposeEmail组件
// 实际实现中可以使用状态管理或props
}
const
loadInitialData
=
()
=>
{
// 模拟加载初始数据
// 联系人
contacts
.
value
=
[]
// 发件人
senders
.
value
=
[]
// 变量
variables
.
value
=
[]
// 变量模板
variableTemplates
.
value
=
[]
// 邮件记录
emails
.
value
=
[]
}
// 初始化
// 初始化
onMounted
(()
=>
{
onMounted
(()
=>
{
// 检查是否已登录(实际项目中应该检查本地存储或令牌)
// 检查是否已登录(实际项目中应该检查本地存储或令牌)
if
(
isAuthenticated
.
value
)
{
if
(
isAuthenticated
.
value
)
{
loadInitialData
()
}
}
})
})
</
script
>
</
script
>
src/api/api.ts
View file @
4de2993b
...
@@ -35,7 +35,7 @@ export const editContact = (data) => {
...
@@ -35,7 +35,7 @@ export const editContact = (data) => {
* @returns
* @returns
*/
*/
export
const
deleteContact
=
(
id
:
number
)
=>
{
export
const
deleteContact
=
(
id
:
number
)
=>
{
return
request
.
delete
(
'/emailContact/del?contactBizId='
+
id
,
{
params
:
{
contactBizId
:
id
}
}
)
return
request
.
delete
(
'/emailContact/del?contactBizId='
+
id
)
}
}
// 获取联系人详情
// 获取联系人详情
...
@@ -74,6 +74,28 @@ export const getContactList = (params: {
...
@@ -74,6 +74,28 @@ export const getContactList = (params: {
return
request
.
post
(
'/emailContact/page'
,
params
)
return
request
.
post
(
'/emailContact/page'
,
params
)
}
}
/**服务商列表 */
/**
*
* @param params {
"providerName": "", //邮箱服务商名称
"pageNo": 1,
"pageSize": 1,
"sortField": "",
"sortOrder": ""
}
* @returns
*/
export
const
getEmailProviderList
=
(
params
:
{
providerName
?:
string
pageNo
?:
number
pageSize
?:
number
sortField
?:
string
sortOrder
?:
string
})
=>
{
return
request
.
post
(
'/emailProviderConfig/page'
,
params
)
}
// 新增发送配置
// 新增发送配置
/**
/**
*
*
...
@@ -81,13 +103,11 @@ export const getContactList = (params: {
...
@@ -81,13 +103,11 @@ export const getContactList = (params: {
* @returns
* @returns
*/
*/
export
const
addEmailSenderConfig
=
(
data
:
{
export
const
addEmailSenderConfig
=
(
data
:
{
emailSenderConfigBizId
?:
number
email
?:
number
emailSenderConfigName
?:
string
password
?:
string
emailSenderConfigEmail
?:
string
providerBizId
?:
string
emailSenderConfigType
?:
string
displayName
?:
string
emailSenderConfigAppellation
?:
string
active
?:
boolean
emailSenderConfigOther
?:
string
emailSenderConfigCcEmailList
?:
string
[]
})
=>
{
})
=>
{
return
request
.
post
(
'/emailSenderConfig/add'
,
data
)
return
request
.
post
(
'/emailSenderConfig/add'
,
data
)
}
}
...
@@ -99,13 +119,12 @@ export const addEmailSenderConfig = (data: {
...
@@ -99,13 +119,12 @@ export const addEmailSenderConfig = (data: {
* @returns
* @returns
*/
*/
export
const
editEmailSenderConfig
=
(
data
:
{
export
const
editEmailSenderConfig
=
(
data
:
{
emailSenderConfigBizId
?:
number
senderBizId
?:
number
emailSenderConfigName
?:
string
email
?:
string
emailSenderConfigEmail
?:
string
password
?:
string
emailSenderConfigType
?:
string
providerBizId
?:
string
emailSenderConfigAppellation
?:
string
displayName
?:
string
emailSenderConfigOther
?:
string
active
?:
number
emailSenderConfigCcEmailList
?:
string
[]
})
=>
{
})
=>
{
return
request
.
put
(
'/emailSenderConfig/edit'
,
data
)
return
request
.
put
(
'/emailSenderConfig/edit'
,
data
)
}
}
...
@@ -116,8 +135,8 @@ export const editEmailSenderConfig = (data: {
...
@@ -116,8 +135,8 @@ export const editEmailSenderConfig = (data: {
* @param id 发送配置id
* @param id 发送配置id
* @returns
* @returns
*/
*/
export
const
deleteEmailSenderConfig
=
(
id
:
number
)
=>
{
export
const
deleteEmailSenderConfig
=
(
id
:
string
)
=>
{
return
request
.
delete
(
'/emailSenderConfig/del
ete'
,
{
params
:
{
emailSenderConfigBizId
:
id
}
}
)
return
request
.
delete
(
'/emailSenderConfig/del
?senderBizId='
+
id
)
}
}
// 获取发送配置详情
// 获取发送配置详情
...
@@ -126,8 +145,8 @@ export const deleteEmailSenderConfig = (id: number) => {
...
@@ -126,8 +145,8 @@ export const deleteEmailSenderConfig = (id: number) => {
* @param id 发送配置id
* @param id 发送配置id
* @returns
* @returns
*/
*/
export
const
getEmailSenderConfigDetail
=
(
id
:
number
)
=>
{
export
const
getEmailSenderConfigDetail
=
(
id
:
string
)
=>
{
return
request
.
get
(
'/emailSenderConfig/detail'
,
{
params
:
{
emailSenderConfig
BizId
:
id
}
})
return
request
.
get
(
'/emailSenderConfig/detail'
,
{
params
:
{
sender
BizId
:
id
}
})
}
}
// 获取发送配置列表
// 获取发送配置列表
...
...
src/router/index.ts
View file @
4de2993b
...
@@ -6,7 +6,7 @@ const router = createRouter({
...
@@ -6,7 +6,7 @@ const router = createRouter({
routes
:
[
routes
:
[
{
{
path
:
'/'
,
path
:
'/'
,
redirect
:
'/
compose
'
,
redirect
:
'/
login
'
,
},
},
{
{
path
:
'/compose'
,
path
:
'/compose'
,
...
...
src/types/index.ts
View file @
4de2993b
// 联系人类型
// 联系人类型
export
interface
Contact
{
export
interface
Contact
{
id
:
string
contactBizId
?
:
string
name
:
string
name
?
:
string
type
:
string
type
?
:
string
companyName
:
string
companyName
?
:
string
email
:
string
email
?
:
string
ccEmailList
:
string
[]
ccEmailList
?
:
string
[]
other
:
string
other
?
:
string
appellation
:
string
appellation
?
:
string
}
}
// 发件人类型
// 发件人类型
export
interface
Sender
{
export
interface
Sender
{
id
:
string
senderBizId
?:
string
email
:
string
email
?:
string
password
:
string
password
?:
string
smtpServer
:
string
displayName
?:
string
smtpPort
:
string
providerBizId
?:
string
active
?:
number
}
}
// 变量类型
// 变量类型
...
...
src/utils/request.ts
View file @
4de2993b
...
@@ -8,7 +8,7 @@ const request = axios.create({
...
@@ -8,7 +8,7 @@ const request = axios.create({
'Content-Type'
:
'application/json'
,
'Content-Type'
:
'application/json'
,
// Authorization: 'Bearer ' + localStorage.getItem('authToken'),
// Authorization: 'Bearer ' + localStorage.getItem('authToken'),
Authorization
:
Authorization
:
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c2VyXzEwMDEiLCJyb2xlcyI6W10sImlhdCI6MTc1OD
Y5OTA3NywiZXhwIjoxNzU4Nzg1NDc3fQ.LR2fGy0aO6EHsHe9Que8rzCaJ0TSAB9KtJndYMSYvvKOSeNvGawCmjE8kgDeRmyFFOFJ2kt0sk-fGaExgzQHSw
'
,
'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ1c2VyXzEwMDEiLCJyb2xlcyI6W10sImlhdCI6MTc1OD
c4NTY3NCwiZXhwIjoxNzU4ODcyMDc0fQ.tjTO6vdpwLpNjVa1DhxRBdpjZsdhbx6g1TdtpAm7BZBRMwanM_ci7dsnbc8FNXpyfSb-ifXW7ccxwyQbtCaKiQ
'
,
},
},
})
})
...
...
src/views/ComposeEmail.vue
View file @
4de2993b
...
@@ -250,33 +250,14 @@ import {
...
@@ -250,33 +250,14 @@ import {
ImportRecord
,
ImportRecord
,
}
from
'../types'
}
from
'../types'
const
props
=
defineProps
({
const
senders
=
ref
<
Sender
[]
>
([])
senders
:
{
const
contacts
=
ref
<
Contact
[]
>
([])
type
:
Array
as
()
=>
Sender
[],
const
variables
=
ref
<
Variable
[]
>
([])
required
:
true
,
const
variableTemplates
=
ref
<
VariableTemplate
[]
>
([])
},
const
emails
=
ref
<
Email
[]
>
([])
contacts
:
{
type
:
Array
as
()
=>
Contact
[],
required
:
true
,
},
variables
:
{
type
:
Array
as
()
=>
Variable
[],
required
:
true
,
},
variableTemplates
:
{
type
:
Array
as
()
=>
VariableTemplate
[],
required
:
true
,
},
emails
:
{
type
:
Array
as
()
=>
Email
[],
required
:
true
,
},
})
const
emits
=
defineEmits
([
'save-email'
,
'save-import-record'
])
// 状态
// 状态
const
currentSender
=
ref
<
Sender
|
null
>
(
props
.
senders
.
length
>
0
?
props
.
senders
[
0
]
:
null
)
const
currentSender
=
ref
<
Sender
|
null
>
(
senders
.
value
.
length
>
0
?
senders
.
value
[
0
]
:
null
)
const
emailForm
=
ref
<
EmailForm
>
({
const
emailForm
=
ref
<
EmailForm
>
({
to
:
''
,
to
:
''
,
cc
:
''
,
cc
:
''
,
...
@@ -307,8 +288,8 @@ watch(
...
@@ -307,8 +288,8 @@ watch(
},
},
)
)
// 计算属性
const
variablePrefix
=
'{{'
const
variablePrefix
=
'{{'
const
variableNextfix
=
'}}'
// 方法
// 方法
const
handleFileUpload
=
(
e
:
Event
)
=>
{
const
handleFileUpload
=
(
e
:
Event
)
=>
{
...
@@ -325,16 +306,19 @@ const removeAttachment = (index: number) => {
...
@@ -325,16 +306,19 @@ const removeAttachment = (index: number) => {
const
applyVariableTemplate
=
()
=>
{
const
applyVariableTemplate
=
()
=>
{
if
(
!
selectedVariableTemplate
.
value
)
return
if
(
!
selectedVariableTemplate
.
value
)
return
const
variableKeys
=
selectedVariableTemplate
.
value
.
variableIds
.
map
((
id
)
=>
{
const
variableKeys
=
const
variable
=
props
.
variables
.
find
((
v
)
=>
v
.
id
===
id
)
selectedVariableTemplate
.
value
.
variableBizIdList
.
map
((
id
)
=>
{
return
variable
?
variable
.
key
:
''
const
variable
=
variables
.
value
.
find
((
v
)
=>
v
.
variableBizId
===
id
)
})
return
variable
?
variable
.
variableNameEn
:
''
const
variablesText
=
variableKeys
.
map
((
key
)
=>
`
${
variablePrefix
}${
key
}
}`
).
join
(
', '
)
})
||
[]
const
variablesText
=
variableKeys
.
map
((
key
)
=>
`
${
variablePrefix
}${
key
}${
variableNextfix
}
`
)
.
join
(
', '
)
emailForm
.
value
.
content
=
`【使用了模板变量:
${
variablesText
}
】\n\n
${
emailForm
.
value
.
content
}
`
emailForm
.
value
.
content
=
`【使用了模板变量:
${
variablesText
}
】\n\n
${
emailForm
.
value
.
content
}
`
}
}
const
insertVariable
=
(
variable
:
Variable
)
=>
{
const
insertVariable
=
(
variable
:
Variable
)
=>
{
emailForm
.
value
.
content
+=
`
${
variablePrefix
}${
variable
.
key
}
}`
emailForm
.
value
.
content
+=
`
${
variablePrefix
}${
variable
.
variableNameEn
}${
variableNextfix
}
`
showVariableSelector
.
value
=
false
showVariableSelector
.
value
=
false
}
}
...
@@ -366,8 +350,6 @@ const saveImportRecord = (to: string, cc: string) => {
...
@@ -366,8 +350,6 @@ const saveImportRecord = (to: string, cc: string) => {
}
}
importRecords
.
value
.
push
(
newRecord
)
importRecords
.
value
.
push
(
newRecord
)
}
}
emits
(
'save-import-record'
,
importRecords
.
value
)
}
}
// 更新导入记录
// 更新导入记录
...
@@ -375,14 +357,12 @@ const updateImportRecord = (updatedRecord: ImportRecord) => {
...
@@ -375,14 +357,12 @@ const updateImportRecord = (updatedRecord: ImportRecord) => {
const
index
=
importRecords
.
value
.
findIndex
((
record
)
=>
record
.
id
===
updatedRecord
.
id
)
const
index
=
importRecords
.
value
.
findIndex
((
record
)
=>
record
.
id
===
updatedRecord
.
id
)
if
(
index
!==
-
1
)
{
if
(
index
!==
-
1
)
{
importRecords
.
value
[
index
]
=
{
...
updatedRecord
}
importRecords
.
value
[
index
]
=
{
...
updatedRecord
}
emits
(
'save-import-record'
,
importRecords
.
value
)
}
}
}
}
// 删除导入记录
// 删除导入记录
const
deleteImportRecord
=
(
id
:
string
)
=>
{
const
deleteImportRecord
=
(
id
:
string
)
=>
{
importRecords
.
value
=
importRecords
.
value
.
filter
((
record
)
=>
record
.
id
!==
id
)
importRecords
.
value
=
importRecords
.
value
.
filter
((
record
)
=>
record
.
id
!==
id
)
emits
(
'save-import-record'
,
importRecords
.
value
)
}
}
// 修改handleImportContacts方法
// 修改handleImportContacts方法
...
@@ -413,7 +393,6 @@ const saveAsDraft = () => {
...
@@ -413,7 +393,6 @@ const saveAsDraft = () => {
status
:
'draft'
,
status
:
'draft'
,
attachments
:
attachments
.
value
.
map
((
file
)
=>
({
name
:
file
.
name
})),
attachments
:
attachments
.
value
.
map
((
file
)
=>
({
name
:
file
.
name
})),
}
}
emits
(
'save-email'
,
draft
)
alert
(
'草稿已保存'
)
alert
(
'草稿已保存'
)
}
}
...
@@ -447,7 +426,6 @@ const confirmSendEmail = () => {
...
@@ -447,7 +426,6 @@ const confirmSendEmail = () => {
status
:
emailForm
.
value
.
scheduleSend
?
'scheduled'
:
'sent'
,
status
:
emailForm
.
value
.
scheduleSend
?
'scheduled'
:
'sent'
,
attachments
:
attachments
.
value
.
map
((
file
)
=>
({
name
:
file
.
name
})),
attachments
:
attachments
.
value
.
map
((
file
)
=>
({
name
:
file
.
name
})),
}
}
emits
(
'save-email'
,
email
)
emailForm
.
value
=
{
to
:
''
,
cc
:
''
,
subject
:
''
,
content
:
''
,
scheduleSend
:
false
,
sendTime
:
''
}
emailForm
.
value
=
{
to
:
''
,
cc
:
''
,
subject
:
''
,
content
:
''
,
scheduleSend
:
false
,
sendTime
:
''
}
attachments
.
value
=
[]
attachments
.
value
=
[]
selectedVariableTemplate
.
value
=
null
selectedVariableTemplate
.
value
=
null
...
...
src/views/ContactManagement.vue
View file @
4de2993b
<
template
>
<
template
>
<!-- 模板内容与之前保持一致 -->
<div>
<div
class=
"p-4 md:p-6"
>
<div
class=
"bg-white rounded-lg shadow-md p-6 mb-6"
>
<div
class=
"max-w-7xl mx-auto"
>
<div
class=
"flex flex-col md:flex-row md:items-center md:justify-between mb-6 gap-4"
>
<h3
class=
"text-lg font-semibold"
>
添加联系人
</h3>
<button
v-if=
"editingSenderId"
@
click=
"resetForm"
class=
"text-gray-500 hover:text-gray-700"
>
<i
class=
"fas fa-times"
></i>
取消编辑
</button>
</div>
<!-- 页面标题和操作按钮 -->
<!-- 页面标题和操作按钮 -->
<div
class=
"flex flex-col md:flex-row md:items-center md:justify-between mb-6 gap-4"
>
<div
class=
"flex flex-col md:flex-row md:items-center md:justify-between mb-6 gap-4"
>
<div>
<h1
class=
"text-2xl font-bold text-gray-800"
>
联系人管理
</h1>
<p
class=
"text-gray-500 mt-1"
>
管理您的所有联系人信息
</p>
</div>
<div
class=
"flex gap-3"
>
<div
class=
"flex gap-3"
>
<button
@
click=
"showImportModal = true"
class=
"btn-outline flex items-center"
>
<button
@
click=
"showImportModal = true"
class=
"btn-outline flex items-center"
>
<i
class=
"fas fa-upload mr-2"
></i>
批量导入
<i
class=
"fas fa-upload mr-2"
></i>
批量导入
...
@@ -18,171 +18,367 @@
...
@@ -18,171 +18,367 @@
</button>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 搜索和筛选区域 -->
<!-- 搜索和筛选区域 -->
<div
class=
"bg-white rounded-lg shadow-sm p-4 mb-6"
>
<div
class=
"bg-white rounded-lg shadow-sm p-4 mb-6"
>
<div
class=
"flex flex-col md:flex-row gap-4"
>
<div
class=
"flex flex-col md:flex-row gap-4"
>
<div
class=
"relative flex-1"
>
<div
class=
"relative flex-1"
>
<i
class=
"fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"
></i>
<i
class=
"fas fa-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"
></i>
<input
<input
v-model=
"searchQuery"
v-model=
"searchQuery"
type=
"text"
type=
"text"
class=
"w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg"
class=
"w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg"
placeholder=
"搜索联系人姓名、公司或邮箱..."
placeholder=
"搜索联系人姓名、公司或邮箱..."
@
keyup
.
enter=
"searchContacts"
@
keyup
.
enter=
"searchContacts"
/>
/>
</div>
</div>
<div
class=
"flex gap-3 w-full md:w-auto"
>
<div
class=
"flex gap-3 w-full md:w-auto"
>
<select
<select
v-model=
"sortBy"
v-model=
"sortBy"
class=
"w-full md:w-auto px-4 py-2 border border-gray-300 rounded-lg"
class=
"w-full md:w-auto px-4 py-2 border border-gray-300 rounded-lg"
@
change=
"searchContacts"
@
change=
"searchContacts"
>
>
<option
value=
"name"
>
按姓名排序
</option>
<option
value=
"name"
>
按姓名排序
</option>
<option
value=
"company"
>
按公司排序
</option>
<option
value=
"company"
>
按公司排序
</option>
<option
value=
"addedAt"
>
按添加时间排序
</option>
<option
value=
"addedAt"
>
按添加时间排序
</option>
</select>
</select>
<button
@
click=
"resetSearch"
class=
"btn-outline px-4"
>
重置
</button>
<button
@
click=
"resetSearch"
class=
"btn-outline px-4"
>
重置
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 联系人列表 -->
<!-- 联系人列表 -->
<div
class=
"bg-white rounded-lg shadow-sm overflow-hidden"
>
<div
class=
"bg-white rounded-lg shadow-sm overflow-hidden"
>
<div
class=
"overflow-x-auto"
>
<div
class=
"overflow-x-auto"
>
<table
class=
"w-full"
>
<table
class=
"w-full"
>
<thead>
<thead>
<tr
class=
"bg-gray-50 border-b border-gray-200"
>
<tr
class=
"bg-gray-50 border-b border-gray-200"
>
<th
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
姓名
</th>
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
称谓
</th>
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
公司
</th>
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
收件人邮箱
</th>
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
抄送人邮箱
</th>
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
其他信息
</th>
<th
class=
"px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"
>
操作
</th>
</tr>
</thead>
<tbody
class=
"divide-y divide-gray-200"
>
<tr
v-for=
"contact in filteredContacts"
:key=
"contact.id"
class=
"hover:bg-gray-50 transition-colors"
>
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
姓名
<div
class=
"flex items-center"
>
</th>
<div
<th
class=
"w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-3"
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
>
<span
class=
"text-sm font-medium"
>
{{
contact
.
name
.
charAt
(
0
)
}}
</span>
称谓
</div>
</th>
<div>
<th
<div
class=
"text-sm font-medium text-gray-900"
>
{{
contact
.
name
}}
</div>
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
</div>
>
</div>
公司
</td>
</th>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<th
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
title
||
'-'
}}
</div>
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
</td>
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
收件人邮箱
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
company
||
'-'
}}
</div>
</th>
</td>
<th
<td
class=
"px-6 py-4 whitespace-nowrap"
>
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
toEmail
}}
</div>
>
</td>
抄送人邮箱
<td
class=
"px-6 py-4"
>
</th>
<div
class=
"flex flex-wrap gap-1"
>
<th
<span
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
v-for=
"(email, index) in contact.ccEmails"
>
:key=
"index"
其他信息
class=
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
</th>
>
<th
{{
email
}}
class=
"px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"
</span>
>
<span
v-if=
"contact.ccEmails.length === 0"
class=
"text-sm text-gray-500"
操作
>
-
</span
</th>
>
</tr>
</thead>
<tbody
class=
"divide-y divide-gray-200"
>
<tr
v-for=
"contact in filteredContacts"
:key=
"contact.contactBizId"
class=
"hover:bg-gray-50 transition-colors"
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<div
class=
"flex items-center"
>
<div
class=
"w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 mr-3"
>
<span
class=
"text-sm font-medium"
>
{{
contact
.
name
?.
charAt
(
0
)
||
'-'
}}
</span>
</div>
</div>
</td>
<div>
<td
class=
"px-6 py-4"
>
<div
class=
"text-sm font-medium text-gray-900"
>
{{
contact
.
name
||
'-'
}}
</div>
<div
class=
"text-sm text-gray-500 line-clamp-2"
>
{{
contact
.
otherInfo
||
'-'
}}
</div>
</div>
</td>
</div>
<td
class=
"px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
>
</td>
<button
<td
class=
"px-6 py-4 whitespace-nowrap"
>
@
click=
"editContact(contact)"
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
appellation
||
'-'
}}
</div>
class=
"text-blue-600 hover:text-blue-900 mr-4"
</td>
title=
"编辑"
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
companyName
||
'-'
}}
</div>
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<div
class=
"text-sm text-gray-500"
>
{{
contact
.
email
||
'-'
}}
</div>
</td>
<td
class=
"px-6 py-4"
>
<div
class=
"flex flex-wrap gap-1"
>
<span
v-for=
"(email, index) in contact.ccEmailList || []"
:key=
"index"
class=
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"
>
>
<i
class=
"fas fa-edit"
></i>
{{
email
}}
</button>
</span>
<span
v-if=
"contact.ccEmailList?.length === 0"
class=
"text-sm text-gray-500"
>
-
</span
>
</div>
</td>
<td
class=
"px-6 py-4"
>
<div
class=
"text-sm text-gray-500 line-clamp-2"
>
{{
contact
.
other
||
'-'
}}
</div>
</td>
<td
class=
"px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
>
<button
@
click=
"editContactModal(contact)"
class=
"text-blue-600 hover:text-blue-900 mr-4"
title=
"编辑"
>
<i
class=
"fas fa-edit"
></i>
</button>
<button
@
click=
"deleteContactModal(contact)"
class=
"text-red-600 hover:text-red-900"
title=
"删除"
>
<i
class=
"fas fa-trash"
></i>
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 空状态、加载状态和分页组件与之前保持一致 -->
</div>
<!-- 联系人模态框 -->
<div
v-if=
"showContactModal"
class=
"fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"
>
<div
class=
"bg-white rounded-lg shadow-xl w-full max-w-2xl max-h-[80vh] flex flex-col"
>
<div
class=
"p-4 border-b border-gray-200 flex justify-between items-center"
>
<h3
class=
"text-lg font-semibold"
>
{{
isEditing
?
'编辑联系人'
:
'新建联系人'
}}
</h3>
<button
@
click=
"closeContactModal"
class=
"text-gray-500 hover:text-gray-700"
>
<i
class=
"fas fa-times"
></i>
</button>
</div>
<div
class=
"p-4 flex-1 overflow-y-auto"
>
<div
class=
"grid grid-cols-1 md:grid-cols-2 gap-4"
>
<!-- 姓名 -->
<div
class=
"md:col-span-2"
>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
姓名 *
</label>
<input
v-model=
"form.name"
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"
placeholder=
"请输入联系人姓名"
/>
<p
v-if=
"errors.name"
class=
"text-red-500 text-xs mt-1"
>
{{
errors
.
name
}}
</p>
</div>
<!-- 联系人类型 -->
<div>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
联系人类型
</label>
<select
v-model=
"form.type"
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"
>
<option
value=
""
>
请选择类型
</option>
<option
value=
"customer"
>
客户
</option>
<option
value=
"partner"
>
合作伙伴
</option>
<option
value=
"supplier"
>
供应商
</option>
<option
value=
"internal"
>
内部员工
</option>
<option
value=
"other"
>
其他
</option>
</select>
</div>
<!-- 称谓 -->
<div>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
称谓
</label>
<input
v-model=
"form.appellation"
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"
placeholder=
"例如:经理、总监"
/>
</div>
<!-- 公司 -->
<div
class=
"md:col-span-2"
>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
公司
</label>
<input
v-model=
"form.companyName"
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"
placeholder=
"请输入公司名称"
/>
</div>
<!-- 收件人邮箱 -->
<div
class=
"md:col-span-2"
>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
收件人邮箱 *
</label>
<input
v-model=
"form.email"
type=
"email"
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=
"example@company.com"
/>
<p
v-if=
"errors.email"
class=
"text-red-500 text-xs mt-1"
>
{{
errors
.
email
}}
</p>
</div>
<!-- 抄送人邮箱 -->
<div
class=
"md:col-span-2"
>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
抄送人邮箱
</label>
<div
class=
"flex gap-2 mb-2"
>
<input
v-model=
"newCcEmail"
type=
"email"
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"
placeholder=
"添加抄送邮箱"
@
keyup
.
enter=
"addCcEmail"
/>
<button
@
click=
"addCcEmail"
class=
"px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-700"
>
添加
</button>
</div>
<div
class=
"flex flex-wrap gap-2"
>
<span
v-for=
"(email, index) in form.ccEmailList"
:key=
"index"
class=
"inline-flex items-center px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm"
>
{{
email
}}
<button
<button
@
click=
"deleteContact(contact.id)"
@
click=
"removeCcEmail(index)"
class=
"text-red-600 hover:text-red-900"
class=
"ml-2 text-blue-600 hover:text-blue-900"
title=
"删除"
>
>
<i
class=
"fas fa-t
rash
"
></i>
<i
class=
"fas fa-t
imes
"
></i>
</button>
</button>
</td>
</span>
</tr>
</div>
</tbody>
</div>
</table>
<!-- 其他信息 -->
<div
class=
"md:col-span-2"
>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
其他信息
</label>
<textarea
v-model=
"form.other"
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"
rows=
"3"
placeholder=
"备注信息"
></textarea>
</div>
</div>
</div>
</div>
<!-- 空状态、加载状态和分页组件与之前保持一致 -->
<div
class=
"p-4 border-t border-gray-200 flex justify-end gap-3"
>
<button
@
click=
"closeContactModal"
class=
"px-6 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors"
>
取消
</button>
<button
@
click=
"saveContact"
:disabled=
"isSubmitting"
class=
"px-6 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-700 transition-colors"
>
{{
isSubmitting
?
'保存中...'
:
isEditing
?
'更新'
:
'保存'
}}
</button>
</div>
</div>
</div>
</div>
</div>
<CommonModal
<!-- 模态框组件与之前保持一致 -->
v-model:visible=
"modalVisible"
:trigger-key=
"modalConfig.triggerKey"
:title=
"modalConfig.title"
type=
"confirm"
:message=
"modalConfig.message"
:show-cancel-button=
"modalConfig.showCancel"
@
confirm=
"handleConfirm"
@
cancel=
"handleCancel"
/>
</div>
</div>
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
computed
,
onMounted
}
from
'vue'
import
{
ref
,
computed
,
onMounted
}
from
'vue'
// 引入我们创建的api拦截器
// 引入我们创建的api拦截器
import
{
editContact
}
from
'@/api/api'
import
{
addContact
,
editContact
,
deleteContact
,
getContactDetail
,
getContactList
,
getEmailSenderConfigList
,
}
from
'@/api/api'
import
{
Contact
,
Sender
}
from
'@/types/index'
// 引入弹窗组件
import
CommonModal
from
'@/components/CommonModal.vue'
import
{
isTypeOnlyImportOrExportDeclaration
}
from
'typescript'
// 弹窗提示信息对象
const
modalVisible
=
ref
(
false
)
const
modalConfig
=
ref
({
showCancel
:
false
,
title
:
'操作确认'
,
message
:
'确定要执行此操作吗?'
,
triggerKey
:
'templateModal'
,
})
// 联系人数据结构
const
openModal
=
(
interface
Contact
{
config
:
{
triggerKey
?:
string
;
showCancel
?:
boolean
;
title
?:
string
;
message
?:
string
}
=
{},
id
:
number
)
=>
{
name
:
string
modalConfig
.
value
=
{
title
?:
string
showCancel
:
config
.
showCancel
??
false
,
company
?:
string
title
:
config
.
title
??
'操作确认'
,
toEmail
:
string
message
:
config
.
message
??
'确定要执行此操作吗?'
,
ccEmailList
:
string
[]
triggerKey
:
config
.
triggerKey
??
modalConfig
.
value
.
triggerKey
,
other
?:
string
}
appellation
?:
string
modalVisible
.
value
=
true
addedAt
:
string
}
const
handleConfirm
=
(
triggerKey
:
string
)
=>
{
modalVisible
.
value
=
false
console
.
log
(
'用户确认操作'
,
triggerKey
)
if
(
triggerKey
===
'deleteContactModal'
)
{
deleteContact
(
form
.
value
.
contactBizId
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
fetchContacts
()
openModal
({
triggerKey
:
''
,
title
:
'成功'
,
message
:
'联系人删除成功'
,
})
}
else
{
openModal
({
triggerKey
:
''
,
title
:
'错误'
,
message
:
res
.
message
||
'联系人删除失败'
,
})
}
})
}
}
}
const
handleCancel
=
(
triggerKey
:
string
)
=>
{
modalVisible
.
value
=
false
console
.
log
(
'用户取消操作'
,
triggerKey
)
}
// 导入错误数据结构
// 导入错误数据结构
interface
ImportError
{
interface
ImportError
{
row
:
number
row
:
number
...
@@ -209,7 +405,6 @@ const currentPage = ref(1)
...
@@ -209,7 +405,6 @@ const currentPage = ref(1)
const
pageSize
=
ref
(
10
)
const
pageSize
=
ref
(
10
)
const
totalContacts
=
ref
(
0
)
const
totalContacts
=
ref
(
0
)
const
isLoading
=
ref
(
false
)
const
isLoading
=
ref
(
false
)
// 模态框状态
// 模态框状态
const
showContactModal
=
ref
(
false
)
const
showContactModal
=
ref
(
false
)
const
isEditing
=
ref
(
false
)
const
isEditing
=
ref
(
false
)
...
@@ -218,20 +413,20 @@ const showImportResultModal = ref(false)
...
@@ -218,20 +413,20 @@ const showImportResultModal = ref(false)
// 表单数据
// 表单数据
const
form
=
ref
<
Partial
<
Contact
>>
({
const
form
=
ref
<
Partial
<
Contact
>>
({
id
:
0
,
name
:
''
,
name
:
''
,
title
:
''
,
type
:
''
,
company
:
''
,
companyName
:
''
,
toEmail
:
''
,
email
:
''
,
ccEmails
:
[],
ccEmailList
:
[],
otherInfo
:
''
,
other
:
''
,
appellation
:
''
,
})
})
const
newCcEmail
=
ref
(
''
)
const
newCcEmail
=
ref
(
''
)
// 表单错误
// 表单错误
const
errors
=
ref
({
const
errors
=
ref
({
name
:
''
,
name
:
''
,
toE
mail
:
''
,
e
mail
:
''
,
})
})
// 导入相关状态
// 导入相关状态
...
@@ -264,21 +459,24 @@ const totalPages = computed(() => {
...
@@ -264,21 +459,24 @@ const totalPages = computed(() => {
return
Math
.
ceil
(
totalContacts
.
value
/
pageSize
.
value
)
return
Math
.
ceil
(
totalContacts
.
value
/
pageSize
.
value
)
})
})
// 获取联系人列表
- 使用api拦截器
// 获取联系人列表
const
fetchContacts
=
async
()
=>
{
const
fetchContacts
=
async
()
=>
{
try
{
try
{
isLoading
.
value
=
true
isLoading
.
value
=
true
const
data
=
await
getContactList
({
// 使用我们的api实例,会自动添加Authorization头
pageNo
:
currentPage
.
value
,
const
data
=
await
api
.
get
(
pageSize
:
pageSize
.
value
,
`/contacts?page=
${
currentPage
.
value
}
&size=
${
pageSize
.
value
}
&search=
${
searchQuery
.
value
}
&sort=
${
sortBy
.
value
}
`
,
sortField
:
sortBy
.
value
,
)
sortOrder
:
'asc'
,
})
contacts
.
value
=
data
.
item
s
contacts
.
value
=
data
.
data
.
record
s
totalContacts
.
value
=
data
.
total
totalContacts
.
value
=
data
.
data
.
total
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'获取联系人失败:'
,
error
)
console
.
error
(
'获取联系人失败:'
,
error
)
showError
(
'获取联系人失败,请稍后重试'
)
openModal
({
title
:
'获取联系人失败'
,
message
:
'获取联系人失败,请稍后重试'
,
})
}
finally
{
}
finally
{
isLoading
.
value
=
false
isLoading
.
value
=
false
}
}
...
@@ -309,14 +507,15 @@ const changePage = (page: number) => {
...
@@ -309,14 +507,15 @@ const changePage = (page: number) => {
const
openAddContactModal
=
()
=>
{
const
openAddContactModal
=
()
=>
{
form
.
value
=
{
form
.
value
=
{
name
:
''
,
name
:
''
,
title
:
''
,
type
:
''
,
company
:
''
,
companyName
:
''
,
toEmail
:
''
,
email
:
''
,
ccEmails
:
[],
ccEmailList
:
[],
otherInfo
:
''
,
other
:
''
,
appellation
:
''
,
}
}
newCcEmail
.
value
=
''
newCcEmail
.
value
=
''
errors
.
value
=
{
name
:
''
,
toE
mail
:
''
}
errors
.
value
=
{
name
:
''
,
e
mail
:
''
}
isEditing
.
value
=
false
isEditing
.
value
=
false
showContactModal
.
value
=
true
showContactModal
.
value
=
true
}
}
...
@@ -327,10 +526,10 @@ const closeContactModal = () => {
...
@@ -327,10 +526,10 @@ const closeContactModal = () => {
}
}
// 编辑联系人
// 编辑联系人
const
editContact
=
(
contact
:
Contact
)
=>
{
const
editContact
Modal
=
(
contact
:
Contact
)
=>
{
form
.
value
=
{
...
contact
}
form
.
value
=
{
...
contact
}
newCcEmail
.
value
=
''
newCcEmail
.
value
=
''
errors
.
value
=
{
name
:
''
,
toE
mail
:
''
}
errors
.
value
=
{
name
:
''
,
e
mail
:
''
}
isEditing
.
value
=
true
isEditing
.
value
=
true
showContactModal
.
value
=
true
showContactModal
.
value
=
true
}
}
...
@@ -338,18 +537,18 @@ const editContact = (contact: Contact) => {
...
@@ -338,18 +537,18 @@ const editContact = (contact: Contact) => {
// 验证表单
// 验证表单
const
validateForm
=
():
boolean
=>
{
const
validateForm
=
():
boolean
=>
{
let
isValid
=
true
let
isValid
=
true
errors
.
value
=
{
name
:
''
,
toE
mail
:
''
}
errors
.
value
=
{
name
:
''
,
e
mail
:
''
}
if
(
!
form
.
value
.
name
?.
trim
())
{
if
(
!
form
.
value
.
name
?.
trim
())
{
errors
.
value
.
name
=
'请输入联系人姓名'
errors
.
value
.
name
=
'请输入联系人姓名'
isValid
=
false
isValid
=
false
}
}
if
(
!
form
.
value
.
toE
mail
?.
trim
())
{
if
(
!
form
.
value
.
e
mail
?.
trim
())
{
errors
.
value
.
toE
mail
=
'请输入收件人邮箱'
errors
.
value
.
e
mail
=
'请输入收件人邮箱'
isValid
=
false
isValid
=
false
}
else
if
(
!
/^
[^\s
@
]
+@
[^\s
@
]
+
\.[^\s
@
]
+$/
.
test
(
form
.
value
.
toE
mail
))
{
}
else
if
(
!
/^
[^\s
@
]
+@
[^\s
@
]
+
\.[^\s
@
]
+$/
.
test
(
form
.
value
.
e
mail
))
{
errors
.
value
.
toE
mail
=
'请输入有效的邮箱地址'
errors
.
value
.
e
mail
=
'请输入有效的邮箱地址'
isValid
=
false
isValid
=
false
}
}
...
@@ -367,50 +566,74 @@ const addCcEmail = () => {
...
@@ -367,50 +566,74 @@ const addCcEmail = () => {
}
}
// 检查是否已存在
// 检查是否已存在
if
(
form
.
value
.
ccEmail
s
?.
includes
(
email
))
{
if
(
form
.
value
.
ccEmail
List
?.
includes
(
email
))
{
showError
(
'该邮箱已在抄送人列表中'
)
showError
(
'该邮箱已在抄送人列表中'
)
return
return
}
}
form
.
value
.
ccEmail
s
=
[...(
form
.
value
.
ccEmails
||
[]),
email
]
form
.
value
.
ccEmail
List
=
[...(
form
.
value
.
ccEmailList
||
[]),
email
]
newCcEmail
.
value
=
''
newCcEmail
.
value
=
''
}
}
// 移除抄送人邮箱
// 移除抄送人邮箱
const
removeCcEmail
=
(
index
:
number
)
=>
{
const
removeCcEmail
=
(
index
:
number
)
=>
{
if
(
form
.
value
.
ccEmail
s
)
{
if
(
form
.
value
.
ccEmail
List
)
{
form
.
value
.
ccEmail
s
.
splice
(
index
,
1
)
form
.
value
.
ccEmail
List
.
splice
(
index
,
1
)
}
}
}
}
// 保存联系人
- 使用api拦截器
// 保存联系人
const
saveContact
=
async
()
=>
{
const
saveContact
=
async
()
=>
{
if
(
!
validateForm
())
return
if
(
!
validateForm
())
return
try
{
try
{
isSubmitting
.
value
=
true
isSubmitting
.
value
=
true
const
contactData
=
{
const
contactData
=
{
contactBizId
:
form
.
value
.
contactBizId
||
undefined
,
type
:
form
.
value
.
type
,
name
:
form
.
value
.
name
,
name
:
form
.
value
.
name
,
title
:
form
.
value
.
titl
e
,
companyName
:
form
.
value
.
companyNam
e
,
company
:
form
.
value
.
company
,
email
:
form
.
value
.
email
,
toEmail
:
form
.
value
.
toEmail
,
ccEmailList
:
form
.
value
.
ccEmailList
,
ccEmails
:
form
.
value
.
ccEmails
,
other
:
form
.
value
.
other
,
otherInfo
:
form
.
value
.
otherInfo
,
appellation
:
form
.
value
.
appellation
,
}
}
if
(
isEditing
.
value
&&
form
.
value
.
i
d
)
{
if
(
isEditing
.
value
&&
form
.
value
.
contactBizI
d
)
{
// 更新现有联系人
// 更新现有联系人
await
api
.
put
(
`/contacts/
${
form
.
value
.
id
}
`
,
contactData
)
editContact
({
...
contactData
}).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
openModal
({
title
:
'更新联系人成功'
,
message
:
'联系人已更新'
,
})
closeContactModal
()
fetchContacts
()
}
else
{
openModal
({
title
:
'更新联系人失败'
,
message
:
res
.
msg
||
'保存联系人失败'
,
})
}
})
}
else
{
}
else
{
// 添加新联系人
// 添加新联系人
await
api
.
post
(
'/contacts'
,
contactData
)
await
addContact
(
contactData
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
openModal
({
title
:
'添加联系人成功'
,
message
:
'联系人已添加'
,
})
closeContactModal
()
fetchContacts
()
}
else
{
openModal
({
title
:
'添加联系人失败'
,
message
:
res
.
msg
||
'保存联系人失败'
,
})
}
})
}
}
// 保存成功,刷新列表并关闭模态框
showSuccess
(
isEditing
.
value
?
'联系人已更新'
:
'联系人已添加'
)
closeContactModal
()
fetchContacts
()
}
catch
(
error
)
{
}
catch
(
error
)
{
console
.
error
(
'保存联系人失败:'
,
error
)
console
.
error
(
'保存联系人失败:'
,
error
)
showError
(
error
instanceof
Error
?
error
.
message
:
'保存联系人失败,请稍后重试'
)
showError
(
error
instanceof
Error
?
error
.
message
:
'保存联系人失败,请稍后重试'
)
...
@@ -420,19 +643,14 @@ const saveContact = async () => {
...
@@ -420,19 +643,14 @@ const saveContact = async () => {
}
}
// 删除联系人 - 使用api拦截器
// 删除联系人 - 使用api拦截器
const
deleteContact
=
async
(
id
:
number
)
=>
{
const
deleteContactModal
=
async
(
contact
:
Contact
)
=>
{
if
(
!
confirm
(
'确定要删除这个联系人吗?此操作不可撤销。'
))
{
form
.
value
=
contact
return
if
(
form
.
value
)
{
}
openModal
({
triggerKey
:
'deleteContactModal'
,
try
{
title
:
'删除联系人'
,
await
api
.
delete
(
`/contacts/
${
id
}
`
)
message
:
`确定要删除联系人
${
form
.
value
.
name
}
吗?`
,
})
showSuccess
(
'联系人已删除'
)
fetchContacts
()
}
catch
(
error
)
{
console
.
error
(
'删除联系人失败:'
,
error
)
showError
(
'删除联系人失败,请稍后重试'
)
}
}
}
}
...
...
src/views/EmailManagement.vue
View file @
4de2993b
...
@@ -122,22 +122,14 @@
...
@@ -122,22 +122,14 @@
import
{
ref
,
computed
,
defineProps
,
defineEmits
}
from
'vue'
import
{
ref
,
computed
,
defineProps
,
defineEmits
}
from
'vue'
import
{
Email
}
from
'../types'
import
{
Email
}
from
'../types'
const
props
=
defineProps
({
emails
:
{
type
:
Array
as
()
=>
Email
[],
required
:
true
,
},
})
const
emits
=
defineEmits
([
'reuse-email'
])
// 状态
// 状态
const
emails
=
ref
<
Email
[]
>
([])
const
searchTerm
=
ref
(
''
)
const
searchTerm
=
ref
(
''
)
const
filterStatus
=
ref
(
''
)
const
filterStatus
=
ref
(
''
)
// 计算属性
// 计算属性
const
filteredEmails
=
computed
(()
=>
{
const
filteredEmails
=
computed
(()
=>
{
return
props
.
emails
return
emails
.
value
.
filter
((
email
)
=>
{
.
filter
((
email
)
=>
{
const
matchesSearch
=
const
matchesSearch
=
email
.
subject
.
toLowerCase
().
includes
(
searchTerm
.
value
.
toLowerCase
())
||
email
.
subject
.
toLowerCase
().
includes
(
searchTerm
.
value
.
toLowerCase
())
||
...
@@ -164,9 +156,5 @@ const viewEmailDetail = (email: Email) => {
...
@@ -164,9 +156,5 @@ const viewEmailDetail = (email: Email) => {
const
reuseEmailContent
=
(
email
:
Email
)
=>
{
const
reuseEmailContent
=
(
email
:
Email
)
=>
{
// 触发复用邮件内容事件
// 触发复用邮件内容事件
emits
(
'reuse-email'
,
{
subject
:
email
.
subject
,
content
:
email
.
content
,
})
}
}
</
script
>
</
script
>
src/views/SenderManagement.vue
View file @
4de2993b
...
@@ -27,31 +27,35 @@
...
@@ -27,31 +27,35 @@
/>
/>
</div>
</div>
<div>
<div>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
SMTP服务器 *
</label>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
发件人姓名
</label>
<input
<input
v-model=
"formData.
smtpServer
"
v-model=
"formData.
displayName
"
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=
"例如:
smtp.example.com
"
placeholder=
"例如:
XX公司
"
/>
/>
</div>
</div>
<div>
<div>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
SMTP端口 *
</label>
<label
class=
"block text-gray-700 mb-1 text-sm"
>
邮件服务商 *
</label>
<input
<select
v-model=
"formData.smtpPort"
v-model=
"formData.providerBizId"
type=
"number"
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=
"例如:587"
>
/>
<option
v-for=
"provider in providers"
:value=
"provider.providerBizId"
:key=
"provider.providerBizId"
>
{{
provider
.
providerName
}}
</option>
</select>
</div>
</div>
</div>
</div>
<div
class=
"mt-4 flex justify-end"
>
<div
class=
"mt-4 flex justify-end"
>
<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=
"
:disabled=
"!formData.email || !formData.password || !formData.providerBizId"
!formData.email || !formData.password || !formData.smtpServer || !formData.smtpPort
"
>
>
{{
editingSenderId
?
'更新发件人'
:
'添加发件人'
}}
{{
editingSenderId
?
'更新发件人'
:
'添加发件人'
}}
</button>
</button>
...
@@ -74,12 +78,12 @@
...
@@ -74,12 +78,12 @@
<th
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
>
SMTP服务器
邮箱服务商
</th>
</th>
<th
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
>
SMTP端口
发件人姓名
</th>
</th>
<th
<th
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
class=
"px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
...
@@ -96,8 +100,13 @@
...
@@ -96,8 +100,13 @@
<tbody
class=
"bg-white divide-y divide-gray-200"
>
<tbody
class=
"bg-white divide-y divide-gray-200"
>
<tr
v-for=
"sender in senders"
:key=
"sender.id"
>
<tr
v-for=
"sender in senders"
:key=
"sender.id"
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
{{
sender
.
email
}}
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
{{
sender
.
email
}}
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
{{
sender
.
smtpServer
}}
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
{{
sender
.
smtpPort
}}
</td>
{{
providers
.
find
((
provider
)
=>
provider
.
providerBizId
===
sender
.
providerBizId
)
?.
providerName
||
'未知'
}}
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
{{
sender
.
displayName
}}
</td>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<td
class=
"px-6 py-4 whitespace-nowrap"
>
<span
<span
class=
"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
class=
"px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
...
@@ -109,7 +118,10 @@
...
@@ -109,7 +118,10 @@
<button
@
click=
"editSender(sender)"
class=
"text-blue-600 hover:text-blue-900 mr-3"
>
<button
@
click=
"editSender(sender)"
class=
"text-blue-600 hover:text-blue-900 mr-3"
>
编辑
编辑
</button>
</button>
<button
@
click=
"deleteSender(sender.id)"
class=
"text-red-600 hover:text-red-900"
>
<button
@
click=
"deleteSender(sender.senderBizId)"
class=
"text-red-600 hover:text-red-900"
>
删除
删除
</button>
</button>
</td>
</td>
...
@@ -122,31 +134,94 @@
...
@@ -122,31 +134,94 @@
<p>
暂无发件人邮箱,请添加发件人
</p>
<p>
暂无发件人邮箱,请添加发件人
</p>
</div>
</div>
</div>
</div>
<CommonModal
v-model:visible=
"modalVisible"
:trigger-key=
"modalConfig.triggerKey"
:title=
"modalConfig.title"
type=
"confirm"
:message=
"modalConfig.message"
:show-cancel-button=
"modalConfig.showCancel"
@
confirm=
"handleConfirm"
@
cancel=
"handleCancel"
/>
</div>
</div>
</
template
>
</
template
>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
defineProps
,
defineEmits
}
from
'vue'
import
{
ref
,
defineProps
,
defineEmits
,
onMounted
}
from
'vue'
import
{
Sender
}
from
'../types'
import
{
getEmailSenderConfigList
,
const
props
=
defineProps
({
getEmailProviderList
,
senders
:
{
deleteEmailSenderConfig
,
type
:
Array
as
()
=>
Sender
[],
addEmailSenderConfig
,
required
:
true
,
editEmailSenderConfig
,
},
}
from
'@/api/api'
import
{
Provider
,
Sender
}
from
'@/types'
// 引入弹窗组件
import
CommonModal
from
'@/components/CommonModal.vue'
// 弹窗提示信息对象
const
modalVisible
=
ref
(
false
)
const
modalConfig
=
ref
({
showCancel
:
false
,
title
:
'操作确认'
,
message
:
'确定要执行此操作吗?'
,
triggerKey
:
'templateModal'
,
})
})
const
emits
=
defineEmits
([
'update-senders'
])
const
openModal
=
(
config
:
{
triggerKey
?:
string
;
showCancel
?:
boolean
;
title
?:
string
;
message
?:
string
}
=
{},
)
=>
{
modalConfig
.
value
=
{
showCancel
:
config
.
showCancel
??
false
,
title
:
config
.
title
??
'操作确认'
,
message
:
config
.
message
??
'确定要执行此操作吗?'
,
triggerKey
:
config
.
triggerKey
??
modalConfig
.
value
.
triggerKey
,
}
modalVisible
.
value
=
true
}
const
handleConfirm
=
(
triggerKey
:
string
)
=>
{
modalVisible
.
value
=
false
console
.
log
(
'用户确认操作'
,
triggerKey
)
if
(
triggerKey
===
'deleteModal'
)
{
deleteEmailSenderConfig
(
editingSenderId
.
value
).
then
((
res
)
=>
{
if
(
res
.
code
===
200
)
{
openModal
({
title
:
'删除确认'
,
message
:
'发件人删除成功'
,
triggerKey
:
''
,
})
getSenders
()
resetForm
()
}
else
{
openModal
({
title
:
'删除失败'
,
message
:
res
.
msg
||
'删除失败'
,
triggerKey
:
''
,
})
return
}
})
}
}
const
handleCancel
=
(
triggerKey
:
string
)
=>
{
modalVisible
.
value
=
false
console
.
log
(
'用户取消操作'
,
triggerKey
)
}
// 状态
// 状态
const
senders
=
ref
<
Sender
[]
>
([
...
props
.
senders
])
const
senders
=
ref
<
Sender
[]
>
([])
const
editingSenderId
=
ref
(
''
)
const
editingSenderId
=
ref
(
''
)
const
formData
=
ref
<
Partial
<
Sender
>>
({
const
formData
=
ref
<
Partial
<
Sender
>>
({
email
:
''
,
email
:
''
,
password
:
''
,
password
:
''
,
smtpServer
:
''
,
providerBizId
:
''
,
smtpPort
:
''
,
displayName
:
''
,
active
:
1
,
})
})
// 服务商列表
const
providers
=
ref
<
Provider
[]
>
([])
// 方法
// 方法
const
resetForm
=
()
=>
{
const
resetForm
=
()
=>
{
...
@@ -154,58 +229,108 @@ const resetForm = () => {
...
@@ -154,58 +229,108 @@ const resetForm = () => {
formData
.
value
=
{
formData
.
value
=
{
email
:
''
,
email
:
''
,
password
:
''
,
password
:
''
,
smtpServer
:
''
,
providerBizId
:
''
,
smtpPort
:
''
,
displayName
:
''
,
active
:
1
,
}
}
}
}
const
getProviders
=
()
=>
{
getEmailProviderList
({
providerName
:
''
,
pageNo
:
1
,
pageSize
:
100
,
}).
then
((
res
)
=>
{
providers
.
value
=
res
.
data
?.
records
||
[]
})
}
const
getSenders
=
()
=>
{
getEmailSenderConfigList
({
emailSenderConfigName
:
''
,
pageNo
:
1
,
pageSize
:
100
,
}).
then
((
res
)
=>
{
senders
.
value
=
res
.
data
?.
records
||
[]
})
}
const
saveSender
=
()
=>
{
const
saveSender
=
()
=>
{
if
(
console
.
log
(
formData
.
value
)
!
formData
.
value
.
email
||
if
(
!
formData
.
value
.
email
||
!
formData
.
value
.
password
||
!
formData
.
value
.
providerBizId
)
{
!
formData
.
value
.
password
||
openModal
({
!
formData
.
value
.
smtpServer
||
title
:
'添加失败'
,
!
formData
.
value
.
smtpPort
message
:
'请填写完整邮箱、密码和服务商'
,
)
}
)
return
return
}
if
(
editingSenderId
.
value
)
{
if
(
editingSenderId
.
value
)
{
// 更新现有发件人
// 更新现有发件人
const
index
=
senders
.
value
.
findIndex
((
s
)
=>
s
.
id
===
editingSenderId
.
value
)
editEmailSenderConfig
({
if
(
index
>
-
1
)
{
senderBizId
:
editingSenderId
.
value
,
senders
.
value
[
index
]
=
{
...
formData
.
value
,
...
senders
.
value
[
index
],
}).
then
((
res
)
=>
{
...
formData
.
value
,
if
(
res
.
code
===
200
)
{
}
as
Sender
getSenders
()
emits
(
'update-senders'
,
[...
senders
.
value
])
openModal
({
alert
(
'发件人更新成功'
)
title
:
'更新确认'
,
}
message
:
'发件人更新成功'
,
})
}
else
{
openModal
({
title
:
'更新失败'
,
message
:
res
.
msg
||
'更新失败'
,
})
}
})
}
else
{
}
else
{
// 添加新发件人
// 添加新发件人
const
newSender
:
Sender
=
{
const
newSender
:
Sender
=
{
id
:
Date
.
now
().
toString
(),
email
:
formData
.
value
.
email
||
''
,
email
:
formData
.
value
.
email
||
''
,
password
:
formData
.
value
.
password
||
''
,
password
:
formData
.
value
.
password
||
''
,
smtpServer
:
formData
.
value
.
smtpServer
||
''
,
providerBizId
:
formData
.
value
.
providerBizId
||
''
,
smtpPort
:
formData
.
value
.
smtpPort
||
''
,
displayName
:
formData
.
value
.
displayName
||
''
,
active
:
formData
.
value
.
active
??
1
,
}
}
addEmailSenderConfig
(
newSender
).
then
((
res
)
=>
{
senders
.
value
.
push
(
newSender
)
// 补充异常处理
emits
(
'update-senders'
,
[...
senders
.
value
])
if
(
res
.
code
===
200
)
{
alert
(
'发件人添加成功'
)
getSenders
()
openModal
({
title
:
'添加确认'
,
message
:
'发件人添加成功'
,
})
}
else
{
openModal
({
title
:
'添加失败'
,
message
:
res
.
msg
||
'添加失败'
,
})
}
})
}
}
resetForm
()
resetForm
()
}
}
const
editSender
=
(
sender
:
Sender
)
=>
{
const
editSender
=
(
sender
:
Sender
)
=>
{
editingSenderId
.
value
=
sender
.
id
console
.
log
(
'编辑发件人'
,
sender
)
editingSenderId
.
value
=
sender
.
senderBizId
||
''
formData
.
value
=
{
...
sender
}
formData
.
value
=
{
...
sender
}
}
}
const
deleteSender
=
(
id
:
string
)
=>
{
const
deleteSender
=
(
id
:
string
)
=>
{
if
(
confirm
(
'确定要删除这个发件人吗?'
))
{
console
.
log
(
'删除发件人'
,
id
)
senders
.
value
=
senders
.
value
.
filter
((
sender
)
=>
sender
.
id
!==
id
)
editingSenderId
.
value
=
id
emits
(
'update-senders'
,
[...
senders
.
value
])
openModal
({
}
showCancel
:
true
,
title
:
'删除确认'
,
message
:
'确定要删除这个发件人吗?'
,
triggerKey
:
'deleteModal'
,
})
}
}
onMounted
(()
=>
{
// 初始化服务商列表
getProviders
()
// 初始化发件人列表
getSenders
()
})
</
script
>
</
script
>
src/views/VariableManagement.vue
View file @
4de2993b
...
@@ -340,22 +340,10 @@ const handleCancel = (triggerKey: string) => {
...
@@ -340,22 +340,10 @@ const handleCancel = (triggerKey: string) => {
console
.
log
(
'用户取消操作'
,
triggerKey
)
console
.
log
(
'用户取消操作'
,
triggerKey
)
}
}
const
props
=
defineProps
({
const
variables
=
ref
<
Variable
[]
>
([])
variables
:
{
const
variableTemplates
=
ref
<
VariableTemplate
[]
>
([])
type
:
Array
as
()
=>
Variable
[],
required
:
true
,
},
variableTemplates
:
{
type
:
Array
as
()
=>
VariableTemplate
[],
required
:
true
,
},
})
const
emits
=
defineEmits
([
'update-variables'
,
'update-variable-templates'
])
// 状态
// 状态
const
variables
=
ref
<
Variable
[]
>
([...
props
.
variables
])
const
variableTemplates
=
ref
<
VariableTemplate
[]
>
([...
props
.
variableTemplates
])
const
variablePrefix
=
'{{'
const
variablePrefix
=
'{{'
const
variableNextfix
=
'}}'
const
variableNextfix
=
'}}'
...
@@ -405,13 +393,6 @@ const saveVariable = () => {
...
@@ -405,13 +393,6 @@ const saveVariable = () => {
description
:
variableForm
.
value
.
description
,
description
:
variableForm
.
value
.
description
,
}).
then
(()
=>
{
}).
then
(()
=>
{
// 更新本地变量列表
// 更新本地变量列表
const
index
=
variables
.
value
.
findIndex
((
v
)
=>
v
.
id
===
editingVariableId
.
value
)
if
(
index
>
-
1
)
{
variables
.
value
[
index
]
=
{
...
variables
.
value
[
index
],
...
variableForm
.
value
,
}
}
fetchVariables
()
fetchVariables
()
openModal
({
openModal
({
title
:
'成功'
,
title
:
'成功'
,
...
@@ -638,7 +619,6 @@ const saveVariableTemplate = () => {
...
@@ -638,7 +619,6 @@ const saveVariableTemplate = () => {
.
then
(()
=>
{
.
then
(()
=>
{
// 刷新变量模版列表
// 刷新变量模版列表
fetchVariableTemplates
()
fetchVariableTemplates
()
emits
(
'update-variable-templates'
,
[...
variableTemplates
.
value
])
})
})
.
catch
((
error
)
=>
{
.
catch
((
error
)
=>
{
console
.
error
(
'更新变量模版失败:'
,
error
)
console
.
error
(
'更新变量模版失败:'
,
error
)
...
@@ -664,7 +644,6 @@ const saveVariableTemplate = () => {
...
@@ -664,7 +644,6 @@ const saveVariableTemplate = () => {
.
then
(()
=>
{
.
then
(()
=>
{
// 刷新变量模版列表
// 刷新变量模版列表
fetchVariableTemplates
()
fetchVariableTemplates
()
emits
(
'update-variable-templates'
,
[...
variableTemplates
.
value
])
})
})
.
catch
((
error
)
=>
{
.
catch
((
error
)
=>
{
console
.
error
(
'创建变量模版失败:'
,
error
)
console
.
error
(
'创建变量模版失败:'
,
error
)
...
@@ -692,7 +671,6 @@ const deleteVariableTemplate = (id: string, type?: string) => {
...
@@ -692,7 +671,6 @@ const deleteVariableTemplate = (id: string, type?: string) => {
.
then
(()
=>
{
.
then
(()
=>
{
// 刷新变量模版列表
// 刷新变量模版列表
fetchVariableTemplates
()
fetchVariableTemplates
()
emits
(
'update-variable-templates'
,
[...
variableTemplates
.
value
])
})
})
.
catch
((
error
)
=>
{
.
catch
((
error
)
=>
{
console
.
error
(
'删除变量模版失败:'
,
error
)
console
.
error
(
'删除变量模版失败:'
,
error
)
...
@@ -710,7 +688,7 @@ const deleteVariableTemplate = (id: string, type?: string) => {
...
@@ -710,7 +688,7 @@ const deleteVariableTemplate = (id: string, type?: string) => {
})
})
}
else
{
}
else
{
openModal
({
openModal
({
showC
lose
:
true
,
showC
ancel
:
true
,
title
:
'确认删除'
,
title
:
'确认删除'
,
message
:
'确定删除此变量模版吗?'
,
message
:
'确定删除此变量模版吗?'
,
triggerKey
:
'templeteDelete'
,
triggerKey
:
'templeteDelete'
,
...
...
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