@@ -29,22 +29,51 @@
@click ="switchTab('status')" >
< text > 服务状态 < / text >
< / view >
< view
class = "tab-item"
: class = "{ active: activeTab === 'performance' }"
@click ="switchTab('performance')" >
< text > 服务表现 < / text >
< / view >
< view
class = "tab-item"
: class = "{ active: activeTab === 'reception' }"
@click ="switchTab('reception')" >
< text > 开始接待 < / text >
< / view >
< view
class = "tab-item"
: class = "{ active: activeTab === 'tag' }"
@click ="switchTab('tag')" >
< text > 标签管理 < / text >
< / view >
< / view >
<!-- 服务状态列表 -- >
< scroll-view class = "service-status-list" scroll -y v-if = "activeTab === 'status'" >
< scroll-view
class = "service-status-list"
scroll -y
v-if = "activeTab === 'status'"
@scrolltolower ="onServiceStatusReachBottom" >
< view class = "service-status-toolbar" >
< text class = "toolbar-total" > 共 { { serviceStatusTotal } } 条 < / text >
< input
class = "toolbar-input"
v-model = "serviceStatusQuery.salesName"
placeholder = "所属销售姓名"
placeholder -style = " color : # b0b0b0 "
confirm -type = " search "
@confirm ="onServiceStatusSearch"
/ >
< input
class = "toolbar-input"
v-model = "serviceStatusQuery.customerName"
placeholder = "客户姓名"
placeholder -style = " color : # b0b0b0 "
confirm -type = " search "
@confirm ="onServiceStatusSearch"
/ >
< view class = "toolbar-actions" >
< view class = "toolbar-btn toolbar-btn--refresh" @click ="onServiceStatusRefresh" >
< uni -icons type = "refresh" size = "18" color = "#2A68FF" > < / uni-icons >
< text > 刷新 < / text >
< / view >
< / view >
< / view >
< view
class = "service-card"
v-for = "(item, index) in serviceStatusList"
@@ -63,6 +92,11 @@
< / view >
< / view >
< view class = "customer-info" >
< text class = "customer-name" > 客户 : { { item . customerName || '未知客户' } } < / text >
< text class = "customer-phone" v-if = "item.customerPhone" > 电话 : {{ item.customerPhone }} < / text >
< / view >
< view class = "customer-tags" >
< view
class = "tag-item"
@@ -92,16 +126,17 @@
< / view >
< view class = "service-duration" >
< text > 已服务 { { item . duration } } 分钟 < / text >
< text > { { item . durationText } } < / text >
< / view >
< / view >
< view class = "service-status-empty" v-if = "!serviceStatusLoading && !serviceStatusList.length" >
< text > 暂无服务中记录 < / text >
< / view >
< view class = "service-status-loading-more" v-if = "serviceStatusLoading && serviceStatusList.length" >
< text > 正在加载更多 ... < / text >
< / view >
< / scroll-view >
<!-- 服务表现内容 -- >
< view class = "performance-content" v-if = "activeTab === 'performance'" >
< text class = "empty-text" > 服务表现内容 < / text >
< / view >
<!-- 开始接待表单 -- >
< scroll-view class = "reception-form" scroll -y v-if = "activeTab === 'reception'" >
< view class = "form-card" >
@@ -139,6 +174,15 @@
placeholder = "请输入客户来源"
placeholder -style = " color : # 9ca3af "
/ >
< / view >
< view class = "form-item" >
< text class = "form-item__label" > 门店名称 < / text >
< input
class = "form-item__input"
v-model = "receptionForm.dealershipName"
placeholder = "请输入门店名称"
placeholder -style = " color : # 9ca3af "
/ >
< / view >
< view class = "form-item" >
< text class = "form-item__label" > 性别 < / text >
@@ -208,6 +252,134 @@
< / view >
< / view >
< / scroll-view >
<!-- 标签管理 -- >
< view class = "tag-management" v-if = "activeTab === 'tag'" >
< ! - - 标签列表 - - >
< scroll-view
class = "tag-list"
scroll -y
v-if = "tagViewMode === 'list'" >
< view class = "tag-list-header" >
< text class = "tag-list-total" > 共 { { tagList . length } } 条 < / text >
< view class = "tag-list-btn" @click ="showAddTag" >
< uni -icons type = "plus" size = "18" color = "#2A68FF" > < / uni-icons >
< text > 添加标签 < / text >
< / view >
< / view >
< view
class = "tag-card"
v-for = "(item, index) in tagList"
:key = "index" >
< view class = "tag-card-header" >
< text class = "tag-card-name" > { { item . name } } < / text >
< / view >
< view class = "tag-card-content" >
< view class = "tag-card-item" v-if = "item.detail" >
< text class = "tag-card-label" > 详情 : < / text >
< text class = "tag-card-value" > { { item . detail } } < / text >
< / view >
< view class = "tag-card-item" v-if = "item.remark" >
< text class = "tag-card-label" > 备注 : < / text >
< text class = "tag-card-value" > { { item . remark } } < / text >
< / view >
< / view >
< / view >
< view class = "tag-list-empty" v-if = "!tagList.length" >
< text > 暂无标签 < / text >
< / view >
< / scroll-view >
<!-- 添加标签表单 -- >
< scroll-view
class = "tag-form"
scroll -y
v-if = "tagViewMode === 'add'" >
< view class = "form-card" >
< view class = "form-item" >
< text class = "form-item__label" > 所属行业 < / text >
< input
class = "form-item__input"
v-model = "tagForm.industry"
placeholder = "请输入所属行业"
placeholder -style = " color : # 9ca3af "
/ >
< / view >
< view class = "form-item tag-select-wrapper form-item--half" >
< text class = "form-item__label" > 标签分类 < / text >
< view
class = "tag-select"
@click.stop ="toggleTagTypeDropdown"
>
< text
: class = "tagForm.tagType ? 'form-item__picker-text' : 'form-item__picker-placeholder'"
>
{ { tagForm . tagType || "请选择标签分类" } }
< / text >
< uni-icons type = "bottom" size = "16" color = "#9ca3af" > < / uni-icons >
< / view >
< view
v-if = "showTagTypeDropdown"
class = "tag-select-dropdown"
@click.stop
>
< view
class = "tag-select-dropdown__item"
v-for = "option in tagTypeOptions"
:key = "option"
@click ="selectTagType(option)"
>
< text : class = "{'active': option === tagForm.tagType}" >
{ { option } }
< / text >
< / view >
< / view >
< / view >
< view class = "form-item" >
< text class = "form-item__label" > 标签名 < / text >
< input
class = "form-item__input"
v-model = "tagForm.name"
placeholder = "请输入标签名"
placeholder -style = " color : # 9ca3af "
/ >
< / view >
< view class = "form-item" >
< text class = "form-item__label" > 详情 < / text >
< textarea
class = "form-item__textarea"
v-model = "tagForm.detail"
placeholder = "请输入详情"
placeholder -style = " color : # 9ca3af "
:maxlength = "500"
/ >
< / view >
< view class = "form-item" >
< text class = "form-item__label" > 备注 < / text >
< textarea
class = "form-item__textarea"
v-model = "tagForm.remark"
placeholder = "请输入备注"
placeholder -style = " color : # 9ca3af "
:maxlength = "500"
/ >
< / view >
< / view >
< view class = "form-actions" >
< view class = "form-btn form-btn--cancel" @click ="cancelAddTag" >
< text class = "form-btn__text" > 取消 < / text >
< / view >
< view class = "form-btn form-btn--save" @click ="saveTag" >
< text class = "form-btn__text" > 保存 < / text >
< / view >
< / view >
< / scroll-view >
< view
v-if = "showTagTypeDropdown"
class = "tag-select-mask"
@click ="closeTagTypeDropdown"
> < / view >
< / view >
< / view >
< / view >
< / template >
@@ -229,7 +401,18 @@ import { getApiUrl } from "@/common/config.js";
activeTab : 'status' ,
genderOptions : [ "男" , "女" ] ,
isFetchingContact : false ,
serviceStatusLoading : false ,
serviceStatusTotal : 0 ,
serviceStatusPage : {
current : 1 ,
size : 10
} ,
serviceStatusQuery : {
salesName : '' ,
customerName : ''
} ,
receptionForm : {
id : "" ,
customerName : "" ,
contact : "" ,
customerSource : "" ,
@@ -247,50 +430,148 @@ import { getApiUrl } from "@/common/config.js";
detailedAddress : "" ,
contactCount : 0
} ,
serviceStatusList : [
{
s taffNam e: '三多 ' ,
s tatus : '服务中' ,
duration : 60 ,
tags : [
{ text : '首次到访 ' , color : 'blue' } ,
{ text : '新房交付 ' , color : 'blue' } ,
{ text : '想买床 ' , color : 'orange' }
] ,
alert : {
type : 'risk' ,
title : '投诉风险' ,
message : '客户情绪激动,有投诉风险,请及时介入'
}
} ,
{
staffName : '雅秋' ,
status : '服务中' ,
duration : 55 ,
tags : [
{ text : '新婚夫妇' , color : 'blue' } ,
{ text : '收纳需求' , color : 'blue' } ,
{ text : '毛坯房' , color : 'blue' } ,
{ text : '关注环保' , color : 'orange' }
] ,
alert : {
type : 'reminder' ,
title : '关单提醒' ,
messages : [
'服务已超过2小时,有关单意向' ,
'但价格敏感,提起多次竞品品牌'
]
}
}
]
serviceStatusList : [ ] ,
// 标签管理
tagViewMod e : 'list ' , // 'list' 或 'add'
tagList : [ ] ,
tagForm : {
industry : '家居行业' ,
tagType : '' ,
name : '' ,
detail : '' ,
remark : ''
} ,
tagTypeOptions : [ "接待客户" , "质检SOP" , "客户画像" ] ,
showTagTypeDropdown : false
}
} ,
onLoad ( ) {
this . fetchServiceStatusList ( ) ;
} ,
methods : {
goBack ( ) {
uni . navigateBack ( ) ;
} ,
switchTab ( tab ) {
this . activeTab = tab ;
if ( tab === 'status' ) {
this . fetchServiceStatusList ( ) ;
} else if ( tab === 'tag' ) {
this . tagViewMode = 'list' ;
this . fetchTagList ( ) ;
}
} ,
onServiceStatusSearch ( ) {
if ( this . activeTab !== 'status' ) {
this . activeTab = 'status' ;
}
this . serviceStatusPage . current = 1 ;
this . fetchServiceStatusList ( { force : true } ) ;
} ,
onServiceStatusRefresh ( ) {
this . serviceStatusPage . current = 1 ;
this . fetchServiceStatusList ( { force : true } ) ;
} ,
onServiceStatusReachBottom ( ) {
// 已在加载中或全部加载完成则不再触发
if ( this . serviceStatusLoading ) return ;
if ( this . serviceStatusList . length >= this . serviceStatusTotal ) return ;
this . serviceStatusPage . current += 1 ;
this . fetchServiceStatusList ( ) ;
} ,
async fetchServiceStatusList ( { force = false } = { } ) {
if ( this . serviceStatusLoading && ! force ) {
return ;
}
this . serviceStatusLoading = true ;
try {
const queryParams = {
current : this . serviceStatusPage . current ,
size : this . serviceStatusPage . size ,
syncStatus : '服务中'
} ;
const trimmedSalesName = this . serviceStatusQuery ? . salesName ? . trim ( ) ;
const trimmedCustomerName = this . serviceStatusQuery ? . customerName ? . trim ( ) ;
if ( trimmedSalesName ) {
queryParams . salesName = trimmedSalesName ;
}
if ( trimmedCustomerName ) {
queryParams . customerName = trimmedCustomerName ;
}
const queryString = Object . keys ( queryParams )
. map ( key => ` ${ key } = ${ encodeURIComponent ( queryParams [ key ] ) } ` )
. join ( '&' ) ;
const url = ` ${ getApiUrl ( '/api/audioManagement/list' ) } ? ${ queryString } ` ;
const res = await uni . request ( {
url ,
method : 'GET' ,
timeout : 10000
} ) ;
if ( res . statusCode === 200 && res . data && res . data . success ) {
const records = Array . isArray ( res . data . data ) ? res . data . data : [ ] ;
const mapped = records . map ( item => this . buildServiceStatusItem ( item ) ) ;
// 第一页或强制刷新时重置列表,否则追加
if ( this . serviceStatusPage . current === 1 || force ) {
this . serviceStatusList = mapped ;
} else {
this . serviceStatusList = this . serviceStatusList . concat ( mapped ) ;
}
this . serviceStatusTotal = Number ( res . data . total ) || 0 ;
} else {
this . serviceStatusList = [ ] ;
this . serviceStatusTotal = 0 ;
uni . showToast ( {
title : res . data ? . message || '获取服务中列表失败' ,
icon : 'none'
} ) ;
}
} catch ( error ) {
console . error ( '获取服务中列表失败:' , error ) ;
uni . showToast ( {
title : '获取服务状态失败,请稍后重试' ,
icon : 'none'
} ) ;
} finally {
this . serviceStatusLoading = false ;
}
} ,
buildServiceStatusItem ( record = { } ) {
const formattedUpdateTime = this . formatDateTime ( record . updateTime || record . createTime ) ;
const tags = [ ] ;
if ( record . recordingName ) {
tags . push ( { text : ` 录音: ${ record . recordingName } ` , color : 'blue' } ) ;
}
if ( record . intentionLevel ) {
tags . push ( { text : ` 意向: ${ record . intentionLevel } ` , color : 'orange' } ) ;
}
if ( record . projectName ) {
tags . push ( { text : ` 项目: ${ record . projectName } ` , color : 'blue' } ) ;
}
return {
id : record . id ,
staffName : record . salesName || '未分配销售' ,
status : record . syncStatus || '服务中' ,
customerName : record . customerName || '' ,
customerPhone : record . customerPhone || '' ,
tags ,
durationText : formattedUpdateTime ? ` 最近更新时间: ${ formattedUpdateTime } ` : '最近暂无更新时间'
} ;
} ,
formatDateTime ( value ) {
if ( ! value ) {
return '' ;
}
const date = new Date ( value ) ;
if ( Number . isNaN ( date . getTime ( ) ) ) {
return '' ;
}
const year = date . getFullYear ( ) ;
const month = String ( date . getMonth ( ) + 1 ) . padStart ( 2 , '0' ) ;
const day = String ( date . getDate ( ) ) . padStart ( 2 , '0' ) ;
const hours = String ( date . getHours ( ) ) . padStart ( 2 , '0' ) ;
const minutes = String ( date . getMinutes ( ) ) . padStart ( 2 , '0' ) ;
const seconds = String ( date . getSeconds ( ) ) . padStart ( 2 , '0' ) ;
return ` ${ year } - ${ month } - ${ day } ${ hours } : ${ minutes } : ${ seconds } ` ;
} ,
viewServiceDetail ( item ) {
// 查看服务详情
@@ -300,13 +581,34 @@ import { getApiUrl } from "@/common/config.js";
this . receptionForm . gender = e . detail . value ;
} ,
onContactBlur ( ) {
const contact = this . receptionForm . contact ? . trim ( ) ;
if ( ! contact ) {
return ;
}
if ( ! this . isValidPhoneNumber ( contact ) ) {
uni . showToast ( {
title : "请输入有效的手机号" ,
icon : "none"
} ) ;
return ;
}
this . fetchCustomerByContact ( ) ;
} ,
isValidPhoneNumber ( phone ) {
const normalizedPhone = phone ? . trim ( ) ;
if ( ! normalizedPhone ) {
return false ;
}
return /^1[3-9]\d{9}$/ . test ( normalizedPhone ) ;
} ,
async fetchCustomerByContact ( ) {
const contact = this . receptionForm . contact ? . trim ( ) ;
if ( ! contact || this . isFetchingContact ) {
return ;
}
if ( ! this . isValidPhoneNumber ( contact ) ) {
return ;
}
try {
this . isFetchingContact = true ;
// 统一使用 getApiUrl, 根据 env.js 配置自动切换环境
@@ -319,21 +621,28 @@ import { getApiUrl } from "@/common/config.js";
const list = res . data ? . data ;
if ( res . statusCode === 200 && res . data ? . success && Array . isArray ( list ) && list . length ) {
const customer = list [ 0 ] ;
const retrievedId = customer . id || customer . customerId || "" ;
const resolvedSalesPhone = customer . salesPhone
|| customer . salesMobile
|| customer . salesTel
|| this . receptionForm . salesPhone
|| "" ;
this . receptionForm = {
... this . receptionForm ,
id : retrievedId ? String ( retrievedId ) : this . receptionForm . id ,
customerName : customer . customerName || this . receptionForm . customerName ,
customerSource : customer . customerSource || this . receptionForm . customerSource ,
dealershipId : customer . dealershipId || "" ,
dealershipName : customer . dealershipName || "" ,
salesId : customer . salesId || "" ,
salesName : customer . salesName || "" ,
salesPhone : customer . s alesPhone || "" ,
recordingCount : customer . recordingCount ? ? 0 ,
intendedModel : customer . intendedModel || "" ,
infoCard : customer . infoCard || "" ,
remark : customer . remark || "" ,
detailedAddress : customer . detailedAddress || "" ,
contactCount : customer . contactCount ? ? 0
dealershipId : customer . dealershipId || this . receptionForm . dealershipId ,
dealershipName : customer . dealershipName || this . receptionForm . dealershipName ,
salesId : customer . salesId || this . receptionForm . salesId ,
salesName : customer . salesName || this . receptionForm . salesName ,
salesPhone : String ( resolvedS alesPhone) ,
recordingCount : customer . recordingCount ? ? this . receptionForm . recordingCount ,
intendedModel : customer . intendedModel || this . receptionForm . intendedModel ,
infoCard : customer . infoCard || this . receptionForm . infoCard ,
remark : customer . remark || this . receptionForm . remark ,
detailedAddress : customer . detailedAddress || this . receptionForm . detailedAddress ,
contactCount : customer . contactCount ? ? this . receptionForm . contactCount
} ;
uni . showToast ( {
title : "已填充客户信息" ,
@@ -351,6 +660,7 @@ import { getApiUrl } from "@/common/config.js";
onCancel ( ) {
// 重置表单
this . receptionForm = {
id : "" ,
customerName : "" ,
contact : "" ,
customerSource : "" ,
@@ -389,11 +699,29 @@ import { getApiUrl } from "@/common/config.js";
} ) ;
return ;
}
const trimmedContact = this . receptionForm . contact ? . trim ( ) ;
if ( ! this . isValidPhoneNumber ( trimmedContact ) ) {
uni . showToast ( {
title : "请输入有效的客户电话" ,
icon : "none"
} ) ;
return ;
}
const trimmedSalesPhone = this . receptionForm . salesPhone ? . trim ( ) ;
if ( trimmedSalesPhone && ! this . isValidPhoneNumber ( trimmedSalesPhone ) ) {
uni . showToast ( {
title : "请输入有效的销售电话" ,
icon : "none"
} ) ;
return ;
}
// 构建请求参数
const normalizedCustomerId = this . receptionForm . id ? . toString ( ) . trim ( ) || "" ;
const params = {
id : normalizedCustomerId ,
customerName : this . receptionForm . customerName ? . trim ( ) ,
contact : this . receptionForm . contact ? . trim ( ) ,
contact : trimmedContact ,
customerSource : this . receptionForm . customerSource ? . trim ( ) || "" ,
dealershipId : this . receptionForm . dealershipId ? . trim ( ) || "" ,
dealershipName : this . receptionForm . dealershipName ? . trim ( ) || "" ,
@@ -404,7 +732,7 @@ import { getApiUrl } from "@/common/config.js";
infoCard : this . receptionForm . infoCard ? . trim ( ) || "" ,
remark : this . receptionForm . remark ? . trim ( ) || "" ,
detailedAddress : this . receptionForm . detailedAddress ? . trim ( ) || "" ,
salesPhone : this . receptionForm . salesPhone ? . trim ( ) || "" ,
salesPhone : trimmedSalesPhone || "" ,
contactCount : Number ( this . receptionForm . contactCount ) || 0 ,
operationType : action
} ;
@@ -444,6 +772,99 @@ import { getApiUrl } from "@/common/config.js";
icon : "none"
} ) ;
}
} ,
// 标签管理相关方法
fetchTagList ( ) {
// TODO: 从API获取标签列表
// 目前使用模拟数据
this . tagList = [ ] ;
} ,
showAddTag ( ) {
this . tagViewMode = 'add' ;
this . showTagTypeDropdown = false ;
this . tagForm = {
industry : '家居行业' ,
tagType : '' ,
name : '' ,
detail : '' ,
remark : ''
} ;
} ,
cancelAddTag ( ) {
this . tagViewMode = 'list' ;
this . showTagTypeDropdown = false ;
this . tagForm = {
industry : '家居行业' ,
tagType : '' ,
name : '' ,
detail : '' ,
remark : ''
} ;
} ,
toggleTagTypeDropdown ( ) {
this . showTagTypeDropdown = ! this . showTagTypeDropdown ;
} ,
selectTagType ( option ) {
this . tagForm . tagType = option ;
this . showTagTypeDropdown = false ;
} ,
closeTagTypeDropdown ( ) {
this . showTagTypeDropdown = false ;
} ,
async saveTag ( ) {
// 表单验证
if ( ! this . tagForm . name || ! this . tagForm . name . trim ( ) ) {
uni . showToast ( {
title : "请输入标签名" ,
icon : "none"
} ) ;
return ;
}
try {
uni . showLoading ( {
title : "保存中..."
} ) ;
const payload = {
industry : this . tagForm . industry ? . trim ( ) || '' ,
tagType : this . tagForm . tagType ? . trim ( ) || '' ,
tagName : this . tagForm . name . trim ( ) ,
tagDetail : this . tagForm . detail ? . trim ( ) || '' ,
remark : this . tagForm . remark ? . trim ( ) || ''
} ;
const res = await uni . request ( {
url : getApiUrl ( '/api/industryTags/add' ) ,
method : "POST" ,
data : payload ,
header : {
"Content-Type" : "application/json"
} ,
timeout : 10000
} ) ;
const { statusCode , data } = res ;
if ( statusCode === 200 && data && ( data . success || data . code === 200 ) ) {
uni . showToast ( {
title : data ? . message || "保存成功" ,
icon : "success"
} ) ;
// 保存成功后返回列表并刷新
this . tagViewMode = 'list' ;
this . fetchTagList ( ) ;
} else {
throw new Error ( data ? . message || "保存失败" ) ;
}
} catch ( error ) {
console . error ( "保存标签失败:" , error ) ;
uni . showToast ( {
title : error ? . message || "保存失败,请重试" ,
icon : "none"
} ) ;
} finally {
uni . hideLoading ( ) ;
}
}
}
}
@@ -526,6 +947,52 @@ import { getApiUrl } from "@/common/config.js";
padding : 24 rpx 32 rpx ;
}
. service - status - toolbar {
display : flex ;
flex - wrap : nowrap ;
align - items : center ;
gap : 16 rpx ;
padding : 16 rpx 24 rpx ;
margin - bottom : 24 rpx ;
background - color : # F8F8FA ;
border - radius : 16 rpx ;
border : 1 px solid # EFEFF2 ;
}
. toolbar - total {
font - size : 26 rpx ;
color : # 666 ;
margin - right : 16 rpx ;
}
. toolbar - input {
flex : 1 ;
min - width : 150 rpx ;
background - color : # F5F6FA ;
border - radius : 12 rpx ;
padding : 16 rpx 24 rpx ;
font - size : 28 rpx ;
border : 1 px solid transparent ;
}
. toolbar - actions {
display : flex ;
align - items : center ;
margin - left : auto ;
}
. toolbar - btn {
padding : 0 16 rpx ;
height : 72 rpx ;
color : # 2 A68FF ;
display : flex ;
align - items : center ;
justify - content : center ;
gap : 8 rpx ;
font - size : 28 rpx ;
font - weight : 400 ;
}
. service - card {
background - color : # FFFFFF ;
border - radius : 16 rpx ;
@@ -587,6 +1054,19 @@ import { getApiUrl } from "@/common/config.js";
gap : 12 rpx ;
}
. customer - info {
margin - bottom : 16 rpx ;
display : flex ;
flex - direction : column ;
gap : 8 rpx ;
}
. customer - name ,
. customer - phone {
font - size : 28 rpx ;
color : # 555 ;
}
. tag - item {
padding : 8 rpx 16 rpx ;
border - radius : 8 rpx ;
@@ -707,15 +1187,11 @@ import { getApiUrl } from "@/common/config.js";
color : # 999 ;
}
/* 服务表现内容 */
. performance - content {
padding : 40 rpx ;
. service - status - empty {
padding : 48 rpx 0 ;
text - align : center ;
}
. empty - text {
font - size : 28 rpx ;
color : # 999 ;
font - size : 28 rpx ;
}
/* 开始接待表单样式 */
@@ -769,6 +1245,10 @@ import { getApiUrl } from "@/common/config.js";
flex - shrink : 0 ;
}
. form - item -- half {
width : 50 % ;
}
. form - item _ _input {
flex : 1 ;
height : 88 rpx ;
@@ -823,6 +1303,67 @@ import { getApiUrl } from "@/common/config.js";
color : # 9 ca3af ;
}
. tag - select - wrapper {
position : relative ;
width : 50 % ;
}
. tag - select {
flex : 1 ;
height : 88 rpx ;
background - color : # f9fafb ;
border - radius : 12 rpx ;
padding : 0 24 rpx ;
display : flex ;
align - items : center ;
justify - content : space - between ;
box - sizing : border - box ;
border : 1 px solid transparent ;
}
. tag - select - dropdown {
position : absolute ;
top : 100 % ;
left : 160 rpx ;
width : calc ( 100 % - 160 rpx ) ;
min - width : 260 rpx ;
max - width : none ;
background - color : # fff ;
border - radius : 16 rpx ;
box - shadow : 0 12 rpx 30 rpx rgba ( 15 , 23 , 42 , 0.1 ) ;
margin - top : 8 rpx ;
z - index : 11 ;
padding : 12 rpx 0 ;
}
. tag - select - dropdown _ _item {
padding : 20 rpx 32 rpx ;
}
. tag - select - dropdown _ _item text {
font - size : 28 rpx ;
color : # 374151 ;
}
. tag - select - dropdown _ _item text . active {
color : # 2 A68FF ;
font - weight : 500 ;
}
. tag - select - dropdown _ _item : active {
background - color : # f5f7fb ;
}
. tag - select - mask {
position : fixed ;
top : 0 ;
left : 0 ;
right : 0 ;
bottom : 0 ;
background - color : transparent ;
z - index : 10 ;
}
. form - actions {
display : flex ;
gap : 24 rpx ;
@@ -866,4 +1407,113 @@ import { getApiUrl } from "@/common/config.js";
. form - btn -- save . form - btn _ _text {
color : # ffffff ;
}
/* 标签管理样式 */
. tag - management {
height : calc ( 100 vh - 300 rpx ) ;
background - color : # F5F5F5 ;
}
. tag - list {
height : 100 % ;
padding : 24 rpx 32 rpx ;
box - sizing : border - box ;
}
. tag - list - header {
display : flex ;
justify - content : space - between ;
align - items : center ;
margin - bottom : 24 rpx ;
padding : 0 ;
}
. tag - list - total {
font - size : 26 rpx ;
color : # 666 ;
}
. tag - list - btn {
display : flex ;
align - items : center ;
gap : 8 rpx ;
padding : 12 rpx 24 rpx ;
background - color : # E3F2FD ;
border - radius : 12 rpx ;
color : # 2 A68FF ;
font - size : 28 rpx ;
}
. tag - card {
background - color : # FFFFFF ;
border - radius : 16 rpx ;
padding : 32 rpx ;
margin - bottom : 24 rpx ;
margin - left : 0 ;
margin - right : 0 ;
box - shadow : 0 2 rpx 8 rpx rgba ( 0 , 0 , 0 , 0.04 ) ;
box - sizing : border - box ;
}
. tag - card - header {
margin - bottom : 20 rpx ;
}
. tag - card - name {
font - size : 32 rpx ;
font - weight : 500 ;
color : # 333 ;
}
. tag - card - content {
display : flex ;
flex - direction : column ;
gap : 12 rpx ;
}
. tag - card - item {
display : flex ;
flex - direction : column ;
gap : 8 rpx ;
}
. tag - card - label {
font - size : 26 rpx ;
color : # 666 ;
}
. tag - card - value {
font - size : 28 rpx ;
color : # 333 ;
line - height : 1.6 ;
width : 40 % ;
max - width : 40 % ;
word - wrap : break - word ;
word - break : break - all ;
}
. tag - list - empty {
padding : 48 rpx 0 ;
text - align : center ;
color : # 999 ;
font - size : 28 rpx ;
}
. tag - form {
height : 100 % ;
padding : 24 rpx 32 rpx ;
box - sizing : border - box ;
}
. form - item _ _textarea {
flex : 1 ;
min - height : 200 rpx ;
background - color : # f9fafb ;
border - radius : 12 rpx ;
padding : 24 rpx ;
font - size : 28 rpx ;
color : # 333 ;
box - sizing : border - box ;
line - height : 1.6 ;
}
< / style >