修改工单 客户等页面

This commit is contained in:
浅念
2025-07-29 16:42:36 +08:00
parent 695ebbcc71
commit 0cef82279f
12 changed files with 733 additions and 563 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ export class CrmService {
} }
//删除客户 //删除客户
static getcustomerdelete(params: any) { static getcustomerdelete(params: any) {
return request.get<Api.Crm.CrmListData>({ return request.get<any>({
url: '/crm/customer/delete', url: '/crm/customer/delete',
params params
}) })
+4 -3
View File
@@ -40,9 +40,10 @@ export class WorkService {
}) })
} }
//工单状态下拉选择框 //工单状态下拉选择框
static getStatus() { static getStatus(params: any) {
return request.get<Api.Brand.BrandInfo>({ return request.get<Api.Brand.BrandInfo>({
url: '/ticket/ticket/getStatus' url: '/ticket/ticket/getStatus',
params
}) })
} }
//工单沟通记录 //工单沟通记录
@@ -53,7 +54,7 @@ export class WorkService {
}) })
} }
//添加工单记录 ticket/conversation/add //添加工单记录 ticket/conversation/add
static conversationAdd(params:any) { static conversationAdd(params: any) {
return request.post<Api.Work.AddResponse>({ return request.post<Api.Work.AddResponse>({
url: '/ticket/conversation/add', url: '/ticket/conversation/add',
params params
@@ -79,7 +79,7 @@
</div> </div>
</div> --> </div> -->
<!-- 语言 --> <!-- 语言 -->
<div class="btn-box" v-if="showLanguage"> <!-- <div class="btn-box" v-if="showLanguage">
<el-dropdown @command="changeLanguage" popper-class="langDropDownStyle"> <el-dropdown @command="changeLanguage" popper-class="langDropDownStyle">
<div class="btn language-btn"> <div class="btn language-btn">
<i class="iconfont-sys">&#xe611;</i> <i class="iconfont-sys">&#xe611;</i>
@@ -98,7 +98,7 @@
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
</div> </div> -->
<!-- 设置 --> <!-- 设置 -->
<!-- <div class="btn-box" @click="openSetting"> <!-- <div class="btn-box" @click="openSetting">
<el-popover :visible="showSettingGuide" placement="bottom-start" :width="190" :offset="0"> <el-popover :visible="showSettingGuide" placement="bottom-start" :width="190" :offset="0">
@@ -138,7 +138,10 @@
popper-style="border: 1px solid var(--art-border-dashed-color); border-radius: calc(var(--custom-radius) / 2 + 4px); padding: 5px 16px; 5px 16px;" popper-style="border: 1px solid var(--art-border-dashed-color); border-radius: calc(var(--custom-radius) / 2 + 4px); padding: 5px 16px; 5px 16px;"
> >
<template #reference> <template #reference>
<img class="cover" src="@imgs/user/avatar.webp" /> <img
class="cover"
:src="getUserInfo.user.avatar ? getUserInfo.user.avatar : '@imgs/user/avatar.webp'"
/>
</template> </template>
<template #default> <template #default>
<div class="user-menu-box"> <div class="user-menu-box">
@@ -155,15 +158,19 @@
<span class="email">{{ userInfo.user.email }}</span> <span class="email">{{ userInfo.user.email }}</span>
</div> </div>
</div> --> </div> -->
<ul class="user-menu"> <ul class="user-menu" style="border: none">
<li @click="goPage('/system/user-center')"> <li @click="goPage('/system/user-center')">
<i class="menu-icon iconfont-sys">&#xe734;</i> <i class="menu-icon iconfont-sys">&#xe734;</i>
<span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span> <span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span>
</li> </li>
<li @click="goPage('/crmpc/recycle')"> <li @click="goPage('/work/myOrder')">
<i class="menu-icon iconfont-sys">&#xe828;</i>
<span class="menu-txt">我的工单</span>
</li>
<!-- <li @click="goPage('/crmpc/recycle')">
<i class="menu-icon iconfont-sys">&#xe828;</i> <i class="menu-icon iconfont-sys">&#xe828;</i>
<span class="menu-txt">回收站</span> <span class="menu-txt">回收站</span>
</li> </li> -->
<!-- <li @click="goPage('/system/user-center')"> <!-- <li @click="goPage('/system/user-center')">
<i class="menu-icon iconfont-sys">&#xe734;</i> <i class="menu-icon iconfont-sys">&#xe734;</i>
<span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span> <span class="menu-txt">{{ $t('topBar.user.userCenter') }}</span>
@@ -176,10 +183,10 @@
<i class="menu-icon iconfont-sys">&#xe8d6;</i> <i class="menu-icon iconfont-sys">&#xe8d6;</i>
<span class="menu-txt">{{ $t('topBar.user.github') }}</span> <span class="menu-txt">{{ $t('topBar.user.github') }}</span>
</li> --> </li> -->
<li @click="lockScreen()"> <!-- <li @click="lockScreen()">
<i class="menu-icon iconfont-sys">&#xe817;</i> <i class="menu-icon iconfont-sys">&#xe817;</i>
<span class="menu-txt">{{ $t('topBar.user.lockScreen') }}</span> <span class="menu-txt">{{ $t('topBar.user.lockScreen') }}</span>
</li> </li> -->
<div class="line"></div> <div class="line"></div>
<div class="logout-btn" @click="loginOut"> <div class="logout-btn" @click="loginOut">
{{ $t('topBar.user.logout') }} {{ $t('topBar.user.logout') }}
@@ -215,7 +222,7 @@
const settingStore = useSettingStore() const settingStore = useSettingStore()
const userStore = useUserStore() const userStore = useUserStore()
const router = useRouter() const router = useRouter()
const { getUserInfo } = useUserStore()
const { const {
showMenuButton, showMenuButton,
showRefreshButton, showRefreshButton,
@@ -229,7 +236,7 @@
tabStyle tabStyle
} = storeToRefs(settingStore) } = storeToRefs(settingStore)
const { language, getUserInfo: userInfo } = storeToRefs(userStore) const { language } = storeToRefs(userStore)
const { menuList } = storeToRefs(useMenuStore()) const { menuList } = storeToRefs(useMenuStore())
@@ -3,7 +3,10 @@
<div v-if="!isLock"> <div v-if="!isLock">
<el-dialog v-model="visible" :width="370" :show-close="false" @open="handleDialogOpen"> <el-dialog v-model="visible" :width="370" :show-close="false" @open="handleDialogOpen">
<div class="lock-content"> <div class="lock-content">
<img class="cover" src="@imgs/user/avatar.webp" /> <img
class="cover"
:src="getUserInfo.user.avatar ? getUserInfo.user.avatar : '@imgs/user/avatar.webp'"
/>
<div class="username">{{ userInfo.userName }}</div> <div class="username">{{ userInfo.userName }}</div>
<el-form ref="formRef" :model="formData" :rules="rules" @submit.prevent="handleLock"> <el-form ref="formRef" :model="formData" :rules="rules" @submit.prevent="handleLock">
<el-form-item prop="password"> <el-form-item prop="password">
@@ -32,7 +35,10 @@
<div class="unlock-content" v-else> <div class="unlock-content" v-else>
<div class="box"> <div class="box">
<img class="cover" src="@imgs/user/avatar.webp" /> <img
class="cover"
:src="getUserInfo.user.avatar ? getUserInfo.user.avatar : '@imgs/user/avatar.webp'"
/>
<div class="username">{{ userInfo.userName }}</div> <div class="username">{{ userInfo.userName }}</div>
<el-form <el-form
ref="unlockFormRef" ref="unlockFormRef"
@@ -77,7 +83,7 @@
import { mittBus } from '@/utils/sys' import { mittBus } from '@/utils/sys'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
const { getUserInfo } = useUserStore()
const ENCRYPT_KEY = import.meta.env.VITE_LOCK_ENCRYPT_KEY const ENCRYPT_KEY = import.meta.env.VITE_LOCK_ENCRYPT_KEY
const userStore = useUserStore() const userStore = useUserStore()
const { info: userInfo, lockPassword, isLock } = storeToRefs(userStore) const { info: userInfo, lockPassword, isLock } = storeToRefs(userStore)
+41 -14
View File
@@ -6,7 +6,12 @@
<section class="search-bar art-custom-card"> <section class="search-bar art-custom-card">
<el-form v-model:filter="formFilters" label-position="left"> <el-form v-model:filter="formFilters" label-position="left">
<el-row class="search-form-row" :gutter="12"> <el-row class="search-form-row" :gutter="12">
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> <el-col :xs="24" :sm="12" :md="4" :lg="4" :xl="4">
<el-form-item label="关键字" label-width="70px">
<el-input v-model="filter.keyword" placeholder="请输入关键字" />
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="4" :lg="4" :xl="4">
<el-form-item label="状态" label-width="70px"> <el-form-item label="状态" label-width="70px">
<el-select v-model="filter.status"> <el-select v-model="filter.status">
<el-option label="全部" value="" /> <el-option label="全部" value="" />
@@ -16,7 +21,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6"> <el-col :xs="24" :sm="12" :md="4" :lg="4" :xl="4">
<el-form-item label="渠道" label-width="70px"> <el-form-item label="渠道" label-width="70px">
<el-select v-model="filter.channel"> <el-select v-model="filter.channel">
<el-option v-for="v in channelOptions" :key="v.id" :label="v.name" :value="v.id"> <el-option v-for="v in channelOptions" :key="v.id" :label="v.name" :value="v.id">
@@ -39,7 +44,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :xs="24" :sm="24" :md="6" :lg="6" :xl="6" class="action-column"> <el-col :xs="24" :sm="24" :md="4" :lg="4" :xl="4" class="action-column">
<div <div
class="action-buttons-wrapper" class="action-buttons-wrapper"
:style="{ :style="{
@@ -79,6 +84,7 @@
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
> >
<template #default> <template #default>
<el-table-column prop="order_no" label="SN"></el-table-column>
<el-table-column prop="contacts" label="客户名称"></el-table-column> <el-table-column prop="contacts" label="客户名称"></el-table-column>
<el-table-column prop="tel" label="电话"></el-table-column> <el-table-column prop="tel" label="电话"></el-table-column>
<el-table-column prop="phone" label="国家"> <el-table-column prop="phone" label="国家">
@@ -124,7 +130,7 @@
</span> </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="倒计时" min-width="140"> <!-- <el-table-column label="倒计时" min-width="140">
<template #default="scope"> <template #default="scope">
<span :class="getCountdownClass(scope.row.countdown)" v-if="scope.row.status==1"> <span :class="getCountdownClass(scope.row.countdown)" v-if="scope.row.status==1">
<span class="custom-clock-icon" style="margin-right: 4px; vertical-align: middle" <span class="custom-clock-icon" style="margin-right: 4px; vertical-align: middle"
@@ -133,7 +139,7 @@
{{ getCountdown(scope.row.countdown) }} {{ getCountdown(scope.row.countdown) }}
</span> </span>
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column fixed="right" label="操作" width="260px"> <el-table-column fixed="right" label="操作" width="260px">
<template #default="scope"> <template #default="scope">
<div class="follow-action fenpei" @click="onFenpei(scope.row)"> <div class="follow-action fenpei" @click="onFenpei(scope.row)">
@@ -172,7 +178,7 @@
</ArtTable> </ArtTable>
</div> </div>
</div> </div>
<el-dialog v-model="detailDialogVisible" title="详情"> <el-dialog v-model="detailDialogVisible" title="详情" width="700px">
<div class="detail-info-table"> <div class="detail-info-table">
<div class="row"> <div class="row">
<div>客户名称:{{ detailRow.contacts }}</div> <div>客户名称:{{ detailRow.contacts }}</div>
@@ -203,7 +209,7 @@
</div> </div>
</div> </div>
<div class="dtitle">详情内容</div> <div class="dtitle">详情内容</div>
<div v-if="detailRow" v-html="detailRow.content"> <div v-if="detailRow" v-html="detailRow.content" class="detils-content">
</div> </div>
</el-dialog> </el-dialog>
@@ -322,7 +328,8 @@
const filter = ref({ const filter = ref({
status: '', status: '',
time: '', time: '',
channel: '' channel: '',
keyword: ''
}) })
const pagination = reactive({ const pagination = reactive({
currentPage: 1, currentPage: 1,
@@ -356,7 +363,8 @@
filter.value = { filter.value = {
status: '', status: '',
time: '', time: '',
channel: '' channel: '',
keyword: ''
} }
Object.assign(formFilters, { ...filter }) Object.assign(formFilters, { ...filter })
pagination.currentPage = 1 // 重置到第一页 pagination.currentPage = 1 // 重置到第一页
@@ -405,6 +413,7 @@
size: pageSize, size: pageSize,
channel: filter.value.channel, channel: filter.value.channel,
status: filter.value.status, status: filter.value.status,
keyword: filter.value.keyword,
time: formattedTimeRange() time: formattedTimeRange()
} }
const { records, current, size, total } = await manageService.getinquiryList(params) const { records, current, size, total } = await manageService.getinquiryList(params)
@@ -436,6 +445,7 @@
} }
onMounted(() => { onMounted(() => {
getgetChannel()
gettableList() gettableList()
timer.value = window.setInterval(() => { timer.value = window.setInterval(() => {
refreshKey.value++ refreshKey.value++
@@ -498,11 +508,11 @@
whatsapp: '', whatsapp: '',
content: '' content: ''
}) })
editorHtml.value = ''
} }
const addfn = () => { const addfn = () => {
dialogType.value = 'add' dialogType.value = 'add'
reactiveForm() reactiveForm()
getgetChannel()
getMagnitude() getMagnitude()
getarea() getarea()
AddDialogVisible.value = true AddDialogVisible.value = true
@@ -525,22 +535,31 @@
} }
function onDetail(row: any) { function onDetail(row: any) {
row.content = processImages(row.content) // 处理图片
detailRow.value = row detailRow.value = row
detailDialogVisible.value = true detailDialogVisible.value = true
} }
//编辑 //编辑
function processImages(html: string) {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
doc.querySelectorAll('img').forEach((img) => {
img.style.maxWidth = '100%'
img.style.height = 'auto'
})
return doc.body.innerHTML
}
const carrid = ref('') const carrid = ref('')
const onEdit = async (row: any) => { const onEdit = async (row: any) => {
dialogType.value = 'edit' dialogType.value = 'edit'
getgetChannel()
getMagnitude() getMagnitude()
getarea() getarea()
AddDialogVisible.value = true AddDialogVisible.value = true
carrid.value = row.id carrid.value = row.id
addForm = reactive({ addForm = reactive({
channel: row.channel ? row.channel.id : '', channel: row.channelInfo ? row.channelInfo.id : '',
quality: row.quality, quality: row.quality,
country: row.country ? row.country.id : '', country: row.countryInfo ? row.countryInfo.id : '',
email: row.email, email: row.email,
tel: row.tel, tel: row.tel,
contacts: row.contacts, contacts: row.contacts,
@@ -743,7 +762,7 @@
} }
.fenpei { .fenpei {
color: #a233c6 !important; color: #3471ff !important;
} }
.detil { .detil {
@@ -773,6 +792,7 @@
} }
.detail-info-table { .detail-info-table {
padding-left: 15px;
.row { .row {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
@@ -805,5 +825,12 @@
color: #333; color: #333;
font-size: 16px; font-size: 16px;
font-weight: bold; font-weight: bold;
padding-left: 15px;
}
.detils-content {
padding-left: 15px;
img {
max-width: 100% !important;
}
} }
</style> </style>
+2 -2
View File
@@ -9,7 +9,7 @@
{{ isDark ? '&#xe6b5;' : '&#xe725;' }} {{ isDark ? '&#xe6b5;' : '&#xe725;' }}
</i> </i>
</div> --> </div> -->
<ElDropdown @command="changeLanguage" popper-class="langDropDownStyle"> <!-- <ElDropdown @command="changeLanguage" popper-class="langDropDownStyle">
<div class="btn language-btn"> <div class="btn language-btn">
<i class="iconfont-sys icon-language">&#xe611;</i> <i class="iconfont-sys icon-language">&#xe611;</i>
</div> </div>
@@ -26,7 +26,7 @@
</div> </div>
</ElDropdownMenu> </ElDropdownMenu>
</template> </template>
</ElDropdown> </ElDropdown> -->
</div> </div>
<div class="header"> <div class="header">
<ArtLogo class="icon" /> <ArtLogo class="icon" />
+1 -1
View File
@@ -40,7 +40,7 @@
<el-input v-model="form.contacts" placeholder="请输入客户名称" /> <el-input v-model="form.contacts" placeholder="请输入客户名称" />
</el-form-item> </el-form-item>
<el-form-item label="客户性别" prop="sex"> <el-form-item label="客户性别" prop="sex">
<el-radio-group v-model="form.sex" style="justify-content: flex-end; width: 100%"> <el-radio-group v-model="form.sex">
<el-radio label="0">未知</el-radio> <el-radio label="0">未知</el-radio>
<el-radio label="1">男</el-radio> <el-radio label="1">男</el-radio>
<el-radio label="2">女</el-radio> <el-radio label="2">女</el-radio>
+1 -1
View File
@@ -40,7 +40,7 @@
<el-input v-model="form.contacts" placeholder="请输入客户名称" /> <el-input v-model="form.contacts" placeholder="请输入客户名称" />
</el-form-item> </el-form-item>
<el-form-item label="客户性别" prop="sex"> <el-form-item label="客户性别" prop="sex">
<el-radio-group v-model="form.sex" style="justify-content: flex-end; width: 100%"> <el-radio-group v-model="form.sex">
<el-radio :label="0">未知</el-radio> <el-radio :label="0">未知</el-radio>
<el-radio :label="1">男</el-radio> <el-radio :label="1">男</el-radio>
<el-radio :label="2">女</el-radio> <el-radio :label="2">女</el-radio>
+31 -3
View File
@@ -106,11 +106,20 @@
<el-link <el-link
type="primary" type="primary"
underline="never" underline="never"
style="margin-right: 8px"
@click="goAddFollow(scope.row)" @click="goAddFollow(scope.row)"
v-if="hasAuth('crm_customer@follow_add')" v-if="hasAuth('crm_customer@follow_add')"
> >
<i class="iconfont-sys">&#xe6bf;</i> 添加跟进 <i class="iconfont-sys">&#xe6bf;</i> 添加跟进
</el-link> </el-link>
<el-link
type="danger"
underline="never"
@click="delectfn(scope.row)"
v-if="hasAuth('crm_customer@follow_delete')"
>
<i class="iconfont-sys">&#xe6d4;</i> 删除
</el-link>
</template> </template>
</el-table-column> </el-table-column>
</template> </template>
@@ -197,11 +206,11 @@
// 处理表格分页变化 // 处理表格分页变化
const handleSizeChange = (newPageSize: number) => { const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize pagination.pageSize = newPageSize
// getWorkList() gettableList()
} }
const handleCurrentChange = (newCurrentPage: number) => { const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage pagination.currentPage = newCurrentPage
// getWorkList() gettableList()
} }
function statusClass(status: any) { function statusClass(status: any) {
if (status === 0) return 'status-following' if (status === 0) return 'status-following'
@@ -235,6 +244,23 @@
pagination.currentPage = 1 pagination.currentPage = 1
gettableList() gettableList()
} }
//删除
const delectfn = (row: any) => {
ElMessageBox.confirm('确定要删除此用户吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
const res = await CrmService.getcustomerdelete({ id: row.id })
ElMessage.success(res?.message || '提交成功!')
gettableList()
// 你可以在这里调用接口或做后续处理
})
.catch(() => {
// 用户点击了取消
})
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -243,7 +269,9 @@
color: #333; color: #333;
font-weight: bold; font-weight: bold;
} }
:deep(.el-table__empty-block) {
height: 300px !important;
}
:deep(.el-table__body tr.custom-table-row td) { :deep(.el-table__body tr.custom-table-row td) {
border-bottom: 1px solid #f7f9fa !important; border-bottom: 1px solid #f7f9fa !important;
border-right: 1px solid #f7f9fa !important; border-right: 1px solid #f7f9fa !important;
+10 -3
View File
@@ -11,7 +11,7 @@
" "
/> />
<h2 class="name">{{ userInfo.name }}</h2> <h2 class="name">{{ userInfo.name }}</h2>
<p class="des">ID:{{ userInfo.id }}</p> <p class="des">sn:{{ userInfo.sn }}</p>
<div class="outer-info"> <div class="outer-info">
<div class="info-row"> <div class="info-row">
<span class="info-label">电 话:</span> <span class="info-label">电 话:</span>
@@ -67,7 +67,7 @@
<el-input v-model="form.name" :disabled="!isEdit" /> <el-input v-model="form.name" :disabled="!isEdit" />
</ElFormItem> </ElFormItem>
<ElFormItem label="性别" prop="sex" class="right-input"> <ElFormItem label="性别" prop="sex" class="right-input">
<ElSelect v-model="form.sex" placeholder="Select" :disabled="!isEdit"> <ElSelect v-model="form.sex" placeholder="未知" :disabled="!isEdit">
<ElOption <ElOption
v-for="item in options" v-for="item in options"
:key="item.value" :key="item.value"
@@ -141,7 +141,7 @@
class="qrcode-img" class="qrcode-img"
/> />
<span v-else class="qrcode-upload-text"> <span v-else class="qrcode-upload-text">
<img :src="imageUrl" class="qrcode-img" /> <img :src="imageUrls" class="qrcode-img" />
</span> </span>
</div> </div>
</el-upload> </el-upload>
@@ -213,6 +213,7 @@
interface CustomerInfo { interface CustomerInfo {
[key: string]: any [key: string]: any
} }
const imageUrls = ref(imageUrl)
const imageUrlavatar = ref('') const imageUrlavatar = ref('')
const socialize_pic_full = ref('') const socialize_pic_full = ref('')
const countryOptions = ref<any>() const countryOptions = ref<any>()
@@ -263,6 +264,10 @@
// }) // })
const options = [ const options = [
{
value: '',
label: '未知'
},
{ {
value: '1', value: '1',
label: '男' label: '男'
@@ -309,6 +314,8 @@
function handleUploadavatarqrcode(response: any) { function handleUploadavatarqrcode(response: any) {
// 假设返回图片地址字段为 response.url 或 response.data.url // 假设返回图片地址字段为 response.url 或 response.data.url
socialize_pic_full.value = response.url || (response.data && response.data.file_url) || '' socialize_pic_full.value = response.url || (response.data && response.data.file_url) || ''
imageUrls.value = response.url || (response.data && response.data.file_url) || ''
// 如需同步到 form.picture // 如需同步到 form.picture
form.value.socialize_pic = response.url || (response.data && response.data.file_name) || '' form.value.socialize_pic = response.url || (response.data && response.data.file_name) || ''
} }
+216 -143
View File
@@ -1,7 +1,6 @@
<template> <template>
<div class="page-content"> <div class="page-content">
<div v-if="!isMobile"> <div v-if="!isMobile">
<ElRow> <ElRow>
<!-- <ElCol :xs="24" :sm="12" :lg="6"> <!-- <ElCol :xs="24" :sm="12" :lg="6">
<ElInput placeholder="工单编号"></ElInput> <ElInput placeholder="工单编号"></ElInput>
@@ -9,18 +8,28 @@
<div style="width: 12px"></div> <div style="width: 12px"></div>
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2"> <ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
<!-- <ElButton v-ripple>搜索</ElButton> --> <!-- <ElButton v-ripple>搜索</ElButton> -->
<ElButton v-if="hasAuth('work_order_self@add')" @click="showDialog('add')" v-ripple>新增</ElButton> <ElButton v-if="hasAuth('work_order_self@add')" @click="showDialog('add')" v-ripple>
新增
</ElButton>
</ElCol> </ElCol>
</ElRow> </ElRow>
<ArtTable ref="tableRef" row-key="id" :loading="loading" :data="tableData" :currentPage="pagination.currentPage" <ArtTable
:pageSize="pagination.pageSize" :total="pagination.total" @size-change="handleSizeChange" ref="tableRef"
@current-change="handleCurrentChange"> row-key="id"
:loading="loading"
:data="tableData"
:currentPage="pagination.currentPage"
:pageSize="pagination.pageSize"
:total="pagination.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<template #default> <template #default>
<ElTableColumn label="工单编号" prop="code" /> <ElTableColumn label="工单编号" prop="code" />
<ElTableColumn label="问题分类" prop="categorie_id"> <ElTableColumn label="问题分类" prop="categorie_id">
<template #default="scope"> <template #default="scope">
<div v-html="scope.row.categorie?scope.row.categorie.name:''"></div> <div v-html="scope.row.categorie ? scope.row.categorie.name : ''"></div>
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="问题描述" prop="content"> <ElTableColumn label="问题描述" prop="content">
@@ -40,9 +49,27 @@
<ElTableColumn fixed="right" label="操作" width="240px"> <ElTableColumn fixed="right" label="操作" width="240px">
<template #default="scope"> <template #default="scope">
<ElRow> <ElRow>
<el-button v-if="scope.row.status == 1&&hasAuth('work_order_self@edit')" link @click="showDialog('edit', scope.row)"> 编辑 </el-button> <el-button
<el-button v-if="hasAuth('work_order_self@status')" link @click="statusEdit(scope.row)"> 状态编辑 </el-button> v-if="scope.row.status == 1 && hasAuth('work_order_self@edit')"
<el-button v-if="hasAuth('work_order_self@conversation_list')" link @click="openChat(scope.row)"> 查看/回复 </el-button> link
@click="showDialog('edit', scope.row)"
>
编辑
</el-button>
<el-button
v-if="hasAuth('work_order_self@status')"
link
@click="statusEdit(scope.row)"
>
状态编辑
</el-button>
<el-button
v-if="hasAuth('work_order_self@conversation_list')"
link
@click="openChat(scope.row)"
>
查看/回复
</el-button>
<!-- <el-button link @click="deleteRole()"> 删除 </el-button> --> <!-- <el-button link @click="deleteRole()"> 删除 </el-button> -->
</ElRow> </ElRow>
</template> </template>
@@ -50,8 +77,13 @@
</template> </template>
</ArtTable> </ArtTable>
<ElDialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增' : '编辑'" width="60%" align-center> <ElDialog
<ElForm ref="formRef" :model="form" label-width="160px"> v-model="dialogVisible"
:title="dialogType === 'add' ? '新增' : '编辑'"
width="60%"
align-center
>
<ElForm ref="formRef" :model="form" label-width="120px" style="padding-right: 30px">
<ElFormItem label="问题分类" prop="categorie_id"> <ElFormItem label="问题分类" prop="categorie_id">
<ElSelect v-model="form.categorie_id"> <ElSelect v-model="form.categorie_id">
<ElOption v-for="type in categorieSelectList" :key="type.id" :value="type.id" :label="type.name" /> <ElOption v-for="type in categorieSelectList" :key="type.id" :value="type.id" :label="type.name" />
@@ -64,27 +96,63 @@
</ElFormItem> </ElFormItem>
<ElFormItem label="上传附件" prop="attachment"> <ElFormItem label="上传附件" prop="attachment">
<ElUpload <ElUpload
v-model:file-list="fileList"
class="upload-demo"
:action="actionImageUplode"
:headers="uploadHeaders"
multiple
:limit="3"
:on-exceed="handleExceed"
>
<el-button type="primary" :disabled="fileList.length >= 3">上传附件</el-button>
</ElUpload>
<!-- <ElUpload
v-model:file-list="fileList" v-model:file-list="fileList"
class="upload-demo" class="upload-demo"
:action="actionImageUplode" :action="actionImageUplode"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:headers="uploadHeaders" :headers="uploadHeaders"
multiple multiple
:limit="3"> :limit="3"
<el-button type="primary">Click to upload</el-button> >
</ElUpload> <el-button type="primary">上传附件</el-button>
</ElUpload> -->
</ElFormItem>
<ElFormItem label="" prop="">
<!-- 附件预览区 --> <!-- 附件预览区 -->
<div class="attachment-preview" v-if="fileList.length"> <div class="attachment-preview">
<div class="attachment-list"> <div v-if="fileList.length" class="attachment-list">
<div v-for="(file, idx) in fileList" :key="file.name" class="attachment-item"> <div v-for="(file, idx) in fileList" :key="file.name" class="attachment-item">
<template v-if="/\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(file.name)"> <template v-if="/\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(file.name)">
<img :src="file.file_url?file.file_url:file.response.data.file_url" :alt="file.name" class="attachment-thumb" @click="handleImageClick(imageList.findIndex(url => url === file.file_url?file.file_url:file.response.data.file_url))" /> <img
:src="file.file_url ? file.file_url : file.response.data.file_url"
:alt="file.name"
class="attachment-thumb"
@click="
handleImageClick(
imageList.findIndex((url) =>
url === file.file_url ? file.file_url : file.response.data.file_url
)
)
"
/>
</template> </template>
<template v-else-if="/\.(mp4|webm|ogg)$/i.test(file.name)"> <template v-else-if="/\.(mp4|webm|ogg)$/i.test(file.name)">
<video :src="file.file_url?file.file_url:file.response.data.file_url" controls class="attachment-thumb" @click.prevent="handleVideoClick(file.file_url?file.file_url:file.response.data.file_url)"></video> <video
:src="file.file_url ? file.file_url : file.response.data.file_url"
controls
class="attachment-thumb"
@click.prevent="
handleVideoClick(file.file_url ? file.file_url : file.response.data.file_url)
"
></video>
</template> </template>
<template v-else> <template v-else>
<a :href="file.file_url?file.file_url:file.response.data.file_url" target="_blank">{{ file.name }}</a> <a
:href="file.file_url ? file.file_url : file.response.data.file_url"
target="_blank"
>{{ file.name }}</a
>
</template> </template>
<div class="attachment-filename">{{ file.name }}</div> <div class="attachment-filename">{{ file.name }}</div>
</div> </div>
@@ -171,102 +239,102 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus' import type { FormInstance } from 'element-plus'
import { Order } from '@/mock/temp/formData' import { Order } from '@/mock/temp/formData'
import { WorkService } from '@/api/workApi' import { WorkService } from '@/api/workApi'
import { ElImageViewer } from 'element-plus' import { ElImageViewer } from 'element-plus'
import { useAuth } from "@/composables/useAuth"; import { useAuth } from "@/composables/useAuth";
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import { useUploadHeaders } from '@/composables/useUploadHeaders' import { useUploadHeaders } from '@/composables/useUploadHeaders'
const { uploadHeaders } = useUploadHeaders() const { uploadHeaders } = useUploadHeaders()
const { info } = useUserStore() const { info } = useUserStore()
const userid = info.user.id const userid = info.user.id
const { hasAuth } = useAuth(); const { hasAuth } = useAuth();
defineOptions({ name: 'Order' }) defineOptions({ name: 'Order' })
let actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload` let actionImageUplode = `${import.meta.env.VITE_API_URL}/ticket/upload`
const loading = ref(false) const loading = ref(false)
const editorHtml = ref('') // 编辑器内容 const editorHtml = ref('') // 编辑器内容
const dialogVisible = ref(false) const dialogVisible = ref(false)
const dialogVisiblestatus = ref(false) const dialogVisiblestatus = ref(false)
const typeList = ref<any[]>([]) const typeList = ref<any[]>([])
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const { width } = useWindowSize() const { width } = useWindowSize()
const isMobile = computed(() => width.value < 500) const isMobile = computed(() => width.value < 500)
// 抽屉显示状态 // 抽屉显示状态
const isDrawerVisible = ref(false) const isDrawerVisible = ref(false)
import meAvatar from '@/assets/img/avatar/avatar5.webp' import meAvatar from '@/assets/img/avatar/avatar5.webp'
import aiAvatar from '@/assets/img/avatar/avatar10.webp' import aiAvatar from '@/assets/img/avatar/avatar10.webp'
// 消息相关数据 // 消息相关数据
const messages = ref<any[]>([]) const messages = ref<any[]>([])
const messageText = ref('') const messageText = ref('')
// 滚动到底部 // 滚动到底部
const messageContainer = ref<HTMLElement | null>(null) const messageContainer = ref<HTMLElement | null>(null)
const scrollToBottom = () => { const scrollToBottom = () => {
setTimeout(() => { setTimeout(() => {
if (messageContainer.value) { if (messageContainer.value) {
messageContainer.value.scrollTop = messageContainer.value.scrollHeight messageContainer.value.scrollTop = messageContainer.value.scrollHeight
} }
}, 100) }, 100)
} }
const openChat = (row: any) => { const openChat = (row: any) => {
isDrawerVisible.value = true isDrawerVisible.value = true
getConversationList(row.id) getConversationList(row.id)
} }
const closeChat = () => { const closeChat = () => {
isDrawerVisible.value = false isDrawerVisible.value = false
} }
//获取状态 下拉框 getStatus //获取状态 下拉框 getStatus
const statusList = ref<any>() const statusList = ref<any>()
const getstatusList = async () => { const getstatusList = async (id: any) => {
try { try {
// 这里调用获取品牌列表的接口 // 这里调用获取品牌列表的接口
const response = await WorkService.getStatus() const response = await WorkService.getStatus({ id: id })
statusList.value = response || [] statusList.value = response || []
} catch (error) { } } catch (error) { }
} }
//获取工单分类 //获取工单分类
const categorieSelectList = ref<any>() const categorieSelectList = ref<any>()
const getcategorieSelectList = async () => { const getcategorieSelectList = async () => {
try { try {
// 这里调用获取品牌列表的接口 // 这里调用获取品牌列表的接口
const response = await WorkService.getcategorieselect() const response = await WorkService.getcategorieselect()
categorieSelectList.value = response || [] categorieSelectList.value = response || []
} catch (error) { } } catch (error) { }
} }
const fileList = ref<any[]>([]) const fileList = ref<any[]>([])
const form = reactive<Order>({ const form = reactive<Order>({
id: '', id: '',
categorie_id: '', categorie_id: '',
content: '', content: '',
attachment: [] attachment: []
}) })
const pagination = reactive({ const pagination = reactive({
currentPage: 1, currentPage: 1,
pageSize: 10, pageSize: 10,
total: 0 total: 0
}) })
const paginationmsg = reactive({ const paginationmsg = reactive({
currentPage: 1, currentPage: 1,
pageSize: 10, pageSize: 10,
total: 0 total: 0
}) })
// 表格数据 // 表格数据
const tableData = ref<any[]>([]) const tableData = ref<any[]>([])
// 表格实例引用 // 表格实例引用
const tableRef = ref() const tableRef = ref()
onMounted(() => { onMounted(() => {
getWorkList() getWorkList()
}) })
// 获取列表数据 // 获取列表数据
const getWorkList = async () => { const getWorkList = async () => {
loading.value = true loading.value = true
try { try {
const { currentPage, pageSize } = pagination const { currentPage, pageSize } = pagination
@@ -284,11 +352,11 @@ const getWorkList = async () => {
} finally { } finally {
loading.value = false loading.value = false
} }
} }
//获取工单记录 getconversationList //获取工单记录 getconversationList
const ticket_id =ref() const ticket_id =ref()
const getConversationList = async (id:any) => { const getConversationList = async (id:any) => {
loading.value = true loading.value = true
try { try {
const { currentPage, pageSize } = paginationmsg const { currentPage, pageSize } = paginationmsg
@@ -307,9 +375,9 @@ const getConversationList = async (id:any) => {
} finally { } finally {
loading.value = false loading.value = false
} }
} }
// 发送工单记录消息 // 发送工单记录消息
const sendMessage = async () => { const sendMessage = async () => {
const text = messageText.value.trim() const text = messageText.value.trim()
const ids = ticket_id.value const ids = ticket_id.value
if (!text) return if (!text) return
@@ -322,12 +390,12 @@ const sendMessage = async () => {
messageText.value = '' messageText.value = ''
getConversationList(ids) getConversationList(ids)
scrollToBottom() scrollToBottom()
} }
const dialogType = ref('add') const dialogType = ref('add')
const showDialog = (type: string, row?: any) => { const showDialog = (type: string, row?: any) => {
dialogVisible.value = true dialogVisible.value = true
dialogType.value = type dialogType.value = type
getcategorieSelectList() getcategorieSelectList()
@@ -353,20 +421,20 @@ const showDialog = (type: string, row?: any) => {
fileList.value = [] fileList.value = []
uploadedFiles.value = [] uploadedFiles.value = []
} }
} }
const statusform = reactive({ const statusform = reactive({
id: '', id: '',
status: '', status: '',
msg: '' msg: ''
}) })
const statusEdit = (row: any) => { const statusEdit = (row: any) => {
getstatusList() getstatusList(row.id)
dialogVisiblestatus.value = true dialogVisiblestatus.value = true
statusform.id = row.id statusform.id = row.id
} }
const deleteRole = () => { const deleteRole = () => {
ElMessageBox.confirm('确定删除该角色吗?', '删除确认', { ElMessageBox.confirm('确定删除该角色吗?', '删除确认', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
@@ -374,31 +442,36 @@ const deleteRole = () => {
}).then(() => { }).then(() => {
ElMessage.success('删除成功') ElMessage.success('删除成功')
}) })
} }
const delCodeTrim = (content: string): string => { const delCodeTrim = (content: string): string => {
return content.replace(/(\s*)<\/code>/g, '</code>') return content.replace(/(\s*)<\/code>/g, '</code>')
} }
//添加工单 //添加工单
const handleExceed = () => {
const uploadedFiles = ref<any[]>([]) ElMessage.warning('最多上传3个文件')
const handleUploadSuccess = (response: any, uploadFile: any, uploadFiles: any[]) => { }
// 只处理上传成功的文件 const uploadedFiles = ref<any[]>([])
uploadedFiles.value = uploadFiles.filter(item => item.status === 'success').map(item => { const getupfiledata = () => {
uploadedFiles.value = fileList.value
.filter((item) => item.status === 'success')
.map((item) => {
const data = item.response?.data const data = item.response?.data
if (data) { if (data) {
return { return {
id: data.id?data.id:'', id: data.id ? data.id : '',
original_name: data.original_name, original_name: data.original_name,
storage_path: data.storage_path?data.storage_path:data.file_name storage_path: data.storage_path ? data.storage_path : data.file_name
} }
} }
return null return null
}) })
.filter(Boolean) .filter(Boolean)
} }
const handleSubmit = async (formEl: FormInstance | undefined) => { const handleSubmit = async (formEl: FormInstance | undefined) => {
getupfiledata()
const { categorie_id} = form const { categorie_id} = form
editorHtml.value = delCodeTrim(editorHtml.value) editorHtml.value = delCodeTrim(editorHtml.value)
console.log(uploadedFiles.value)
if(dialogType.value === 'add'){ if(dialogType.value === 'add'){
const { message } = await WorkService.WorkAdd({ const { message } = await WorkService.WorkAdd({
content: editorHtml.value, content: editorHtml.value,
@@ -421,19 +494,19 @@ const handleSubmit = async (formEl: FormInstance | undefined) => {
} }
} }
// 处理表格分页变化 // 处理表格分页变化
const handleSizeChange = (newPageSize: number) => { const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize pagination.pageSize = newPageSize
getWorkList() getWorkList()
} }
const handleCurrentChange = (newCurrentPage: number) => { const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage pagination.currentPage = newCurrentPage
getWorkList() getWorkList()
} }
//修改状态 //修改状态
const statusSubmit = async () => { const statusSubmit = async () => {
// loading.value = true // loading.value = true
const { msg, status, id } = statusform const { msg, status, id } = statusform
const { message } = await WorkService.Workstatus({ const { message } = await WorkService.Workstatus({
@@ -444,41 +517,41 @@ const statusSubmit = async () => {
ElMessage.success(message) ElMessage.success(message)
dialogVisiblestatus.value = false dialogVisiblestatus.value = false
getWorkList() getWorkList()
} }
// 图片预览相关 // 图片预览相关
const imageViewerVisible = ref(false) const imageViewerVisible = ref(false)
const imageViewerIndex = ref(0) const imageViewerIndex = ref(0)
const imageList = computed(() => fileList.value.filter(file => /\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(file.name)).map(file => file.file_url?file.file_url:file.response.data.file_url)) const imageList = computed(() => fileList.value.filter(file => /\.(jpg|jpeg|png|gif|webp|bmp)$/i.test(file.name)).map(file => file.file_url?file.file_url:file.response.data.file_url))
function handleImageClick(idx: number) { function handleImageClick(idx: number) {
imageViewerIndex.value = idx imageViewerIndex.value = idx
imageViewerVisible.value = true imageViewerVisible.value = true
} }
// 视频预览相关 // 视频预览相关
const videoDialogVisible = ref(false) const videoDialogVisible = ref(false)
const currentVideoUrl = ref('') const currentVideoUrl = ref('')
function handleVideoClick(url: string) { function handleVideoClick(url: string) {
currentVideoUrl.value = url currentVideoUrl.value = url
videoDialogVisible.value = true videoDialogVisible.value = true
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
:deep(.el-table__empty-block) { :deep(.el-table__empty-block) {
height: 100% !important; height: 100% !important;
min-height: 200px; min-height: 200px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.multi-line-ellipsis { .multi-line-ellipsis {
overflow: hidden; overflow: hidden;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
word-break: break-all; word-break: break-all;
} }
.page-content { .page-content {
.svg-icon { .svg-icon {
width: 1.8em; width: 1.8em;
height: 1.8em; height: 1.8em;
@@ -486,9 +559,9 @@ function handleVideoClick(url: string) {
vertical-align: -8px; vertical-align: -8px;
fill: currentcolor; fill: currentcolor;
} }
} }
.header { .header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -506,9 +579,9 @@ function handleVideoClick(url: string) {
cursor: pointer; cursor: pointer;
} }
} }
} }
.chat-container { .chat-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: calc(100% - 70px); height: calc(100% - 70px);
@@ -622,9 +695,9 @@ function handleVideoClick(url: string) {
} }
} }
} }
} }
.dark { .dark {
.chat-container { .chat-container {
.chat-messages { .chat-messages {
.message-item { .message-item {
@@ -642,9 +715,9 @@ function handleVideoClick(url: string) {
} }
} }
} }
} }
.attachment-preview { .attachment-preview {
margin-top: 12px; margin-top: 12px;
.attachment-list { .attachment-list {
display: flex; display: flex;
@@ -683,5 +756,5 @@ function handleVideoClick(url: string) {
word-break: break-all; word-break: break-all;
margin-top: 2px; margin-top: 2px;
} }
} }
</style> </style>
+29 -8
View File
@@ -50,7 +50,7 @@
</ArtTable> </ArtTable>
<ElDialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增' : '编辑'" width="60%" align-center> <ElDialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增' : '编辑'" width="60%" align-center>
<ElForm ref="formRef" :model="form" label-width="160px"> <ElForm ref="formRef" :model="form" label-width="120px" style="padding-right: 30px">
<ElFormItem label="问题分类" prop="categorie_id"> <ElFormItem label="问题分类" prop="categorie_id">
<ElSelect v-model="form.categorie_id"> <ElSelect v-model="form.categorie_id">
<ElOption v-for="type in categorieSelectList" :key="type.id" :value="type.id" :label="type.name" /> <ElOption v-for="type in categorieSelectList" :key="type.id" :value="type.id" :label="type.name" />
@@ -69,9 +69,13 @@
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:headers="uploadHeaders" :headers="uploadHeaders"
multiple multiple
:limit="3"> :limit="3"
:on-exceed="handleExceed"
>
<el-button type="primary">上传</el-button> <el-button type="primary">上传</el-button>
</ElUpload> </ElUpload>
</ElFormItem>
<ElFormItem label="" prop="">
<!-- 附件预览区 --> <!-- 附件预览区 -->
<div class="attachment-preview" v-if="fileList.length"> <div class="attachment-preview" v-if="fileList.length">
<div class="attachment-list"> <div class="attachment-list">
@@ -113,8 +117,17 @@
<!-- 聊天消息区域 --> <!-- 聊天消息区域 -->
<div class="chat-messages" ref="messageContainer"> <div class="chat-messages" ref="messageContainer">
<template v-for="(message, index) in messages" :key="index"> <template v-for="(message, index) in messages" :key="index">
<div :class="['message-item', String(message.user_id) === String(userid) ? 'message-right' : 'message-left']"> <div
<el-avatar :size="32" :src="String(message.user_id) === String(userid) ? meAvatar : aiAvatar" class="message-avatar" /> :class="[
'message-item',
String(message.user_id) === String(userid) ? 'message-right' : 'message-left'
]"
>
<el-avatar
:size="32"
:src="String(message.user_id) === String(userid) ? meAvatar : aiAvatar"
class="message-avatar"
/>
<div class="message-content"> <div class="message-content">
<div class="message-info"> <div class="message-info">
<span class="sender-name">{{ message.user_id }}</span> <span class="sender-name">{{ message.user_id }}</span>
@@ -126,8 +139,14 @@
</template> </template>
</div> </div>
<div class="chat-input" v-if="hasAuth('work_order@conversation_add')"> <div class="chat-input" v-if="hasAuth('work_order@conversation_add')">
<el-input v-model="messageText" type="textarea" :rows="3" placeholder="输入消息" resize="none" <el-input
@keyup.enter.prevent="sendMessage" /> v-model="messageText"
type="textarea"
:rows="3"
placeholder="输入消息"
resize="none"
@keyup.enter.prevent="sendMessage"
/>
<ElInput v-model="ticket_id" type="hidden" /> <ElInput v-model="ticket_id" type="hidden" />
<div class="chat-input-actions"> <div class="chat-input-actions">
<el-button type="primary" @click="sendMessage" v-ripple>发送</el-button> <el-button type="primary" @click="sendMessage" v-ripple>发送</el-button>
@@ -224,7 +243,7 @@ const statusList = ref<any>()
const getstatusList = async () => { const getstatusList = async () => {
try { try {
// 这里调用获取品牌列表的接口 // 这里调用获取品牌列表的接口
const response = await WorkService.getStatus() const response = await WorkService.getStatus({})
statusList.value = response || [] statusList.value = response || []
} catch (error) { } } catch (error) { }
} }
@@ -381,7 +400,9 @@ const delCodeTrim = (content: string): string => {
return content.replace(/(\s*)<\/code>/g, '</code>') return content.replace(/(\s*)<\/code>/g, '</code>')
} }
//添加工单 //添加工单
const handleExceed = () => {
ElMessage.warning('最多上传3个文件')
}
const uploadedFiles = ref<any[]>([]) const uploadedFiles = ref<any[]>([])
const handleUploadSuccess = (response: any, uploadFile: any, uploadFiles: any[]) => { const handleUploadSuccess = (response: any, uploadFile: any, uploadFiles: any[]) => {
// 只处理上传成功的文件 // 只处理上传成功的文件