@@ -22,13 +22,11 @@
< / t-form-item >
< t-form-item label = "状态" >
< t-radio-group v-model = "formModel.status" class="inline-options" variant="default-filled" >
< t -radio :block = "false" borderless value = "ACTIVE " > 有效 < / t-radio >
< t-radio :block = "false" borderless value = "IN ACTIVE" > 无效 < / t-radio >
< t -radio :block = "false" borderless value = "DRAFT " > 草稿 < / t-radio >
< t-radio :block = "false" borderless value = "ACTIVE" > 可登记 < / t-radio >
< t-radio :block = "false" borderless value = "INACTIVE" > 不可登记 < / t-radio >
< / t-radio-group >
< / t-form-item >
< t-form-item label = "启用" content -align = " right " >
< t-switch v-model = "formModel.enabled" / >
< / t-form-item >
< t-form-item label = "需要拍照" content -align = " right " >
< t-switch v-model = "formModel.requirePhoto" / >
< / t-form-item >
@@ -51,11 +49,17 @@
< t-form-item v-if = "isValueLimitType(formModel.limitType)" label="数值" >
< t -input v -model .trim = " formModel.limitValueText " type = "number" :placeholder = "limitValuePlaceholder" borderless / >
< / t-form-item >
< t-form-item label = "起始时间" arrow @click ="openBeginAtPicker" >
< div class = "picker-text" v-text = "formModel.beginAtText || '不限'" / >
< / t-form-item >
< t-form-item label = "终止时间" arrow @click ="openEndAtPicker" >
< div class = "picker-text" v-text = "formModel.endAtText || '不限'" / >
< / t-form-item >
< / t-form >
< section class = "roles" >
< div class = "title" >
< span > 可登记角色 < / span >
< span class = "hint" > 未选择角色时不限制角色 < / span >
< span class = "hint" > 必须至少选择一个角色 , 上级角色拥有子级角色可登记事件的登记权限 < / span >
< / div >
< t-checkbox-group v-model = "formModel.roleCodeList" class="group" >
< t -checkbox
@@ -109,9 +113,46 @@
/ >
< / div >
< / t-popup >
< t-popup v-model = "beginAtPickerVisible" placement="bottom" >
< div class = "picker-popup" >
< div class = "picker-header" >
< t-button variant = "text" size = "small" @click ="clearBeginAt" > 清空 < / t -button >
< span v-text = "'起始时间'" / >
< t-button variant = "text" size = "small" @click ="beginAtPickerVisible = false" > 取消 < / t -button >
< / div >
< t-date-time-picker
v-model = "beginAtDraftText"
: default -value = " beginAtDraftText | | nowDateTimeText "
: mode = "['date', 'minute']"
format = "YYYY-MM-DD HH:mm"
title = "起始时间"
@cancel ="beginAtPickerVisible = false"
@confirm ="confirmBeginAt"
/ >
< / div >
< / t-popup >
< t-popup v-model = "endAtPickerVisible" placement="bottom" >
< div class = "picker-popup" >
< div class = "picker-header" >
< t-button variant = "text" size = "small" @click ="clearEndAt" > 清空 < / t -button >
< span v-text = "'终止时间'" / >
< t-button variant = "text" size = "small" @click ="endAtPickerVisible = false" > 取消 < / t -button >
< / div >
< t-date-time-picker
v-model = "endAtDraftText"
: default -value = " endAtDraftText | | nowDateTimeText "
: mode = "['date', 'minute']"
format = "YYYY-MM-DD HH:mm"
title = "终止时间"
@cancel ="endAtPickerVisible = false"
@confirm ="confirmEndAt"
/ >
< / div >
< / t-popup >
< / template >
< script setup lang = "ts" >
import { Time } from "timi-web" ;
import { DialogPlugin , Toast } from "tdesign-mobile-vue" ;
import type { Role } from "timi-web" ;
import RegistrationEventAPI from "@/api/RegistrationEventAPI" ;
@@ -143,6 +184,10 @@ const pageAccess = computed(() => ({
const roleOptions = ref < Role [ ] > ( [ ] ) ;
const colorPickerVisible = ref ( false ) ;
const colorDraft = ref ( "#2f88ff" ) ;
const beginAtPickerVisible = ref ( false ) ;
const endAtPickerVisible = ref ( false ) ;
const beginAtDraftText = ref ( "" ) ;
const endAtDraftText = ref ( "" ) ;
const saving = ref ( false ) ;
const removing = ref ( false ) ;
const colorSwatchList = [
@@ -163,7 +208,8 @@ const limitOptions: LimitOption[] = [
{ label : "每天一次" , value : "NATURAL_DAY" } ,
{ label : "间隔小时" , value : "INTERVAL_HOUR" } ,
{ label : "每月一次" , value : "NATURAL_MONTH" } ,
{ label : "累计 次数" , value : "TOTAL_LIMIT" }
{ label : "事件总 次数" , value : "TOTAL_LIMIT" } ,
{ label : "单客户总次数" , value : "CUSTOMER_TOTAL_LIMIT" }
] ;
const formModel = reactive ( {
id : "" ,
@@ -171,14 +217,24 @@ const formModel = reactive({
description : "" ,
color : "#2f88ff" ,
status : "ACTIVE" as RegistrationEventStatus ,
enabled : true ,
requirePhoto : false ,
limitType : "NONE" as RegistrationLimitType ,
limitValueText : "" ,
beginAtText : "" ,
endAtText : "" ,
sortText : "0" ,
roleCodeList : [ ] as string [ ]
} ) ;
const limitValuePlaceholder = computed ( ( ) => formModel . limitType === "INTERVAL_HOUR" ? "请输入间隔小时数" : "请输入累计上限次数" ) ;
const nowDateTimeText = computed ( ( ) => Time . formatDateTime ( new Date ( ) ) ) ;
const limitValuePlaceholder = computed ( ( ) => {
if ( formModel . limitType === "INTERVAL_HOUR" ) {
return "请输入间隔小时数" ;
}
if ( formModel . limitType === "CUSTOMER_TOTAL_LIMIT" ) {
return "请输入单客户总次数上限" ;
}
return "请输入总次数上限" ;
} ) ;
function openColorPicker ( ) : void {
colorDraft . value = formModel . color ;
@@ -196,7 +252,7 @@ function confirmColorPicker(): void {
}
function isValueLimitType ( value : RegistrationLimitType ) : boolean {
return value === "INTERVAL_HOUR" || value === "TOTAL_LIMIT" ;
return value === "INTERVAL_HOUR" || value === "TOTAL_LIMIT" || value === "CUSTOMER_TOTAL_LIMIT" ;
}
function resolveLimitValue ( ) : number | undefined {
@@ -208,15 +264,35 @@ function resolveLimitValue(): number | undefined {
return 0 < value ? Math . floor ( value ) : undefined ;
}
function resolveTimestamp ( valueText : string ) : number | undefined {
if ( ! valueText . trim ( ) ) {
return undefined ;
}
const date = new Date ( valueText ) ;
const timestamp = Time . toTimestamp ( date ) ;
return Number . isFinite ( timestamp ) ? timestamp : undefined ;
}
function validateForm ( ) : boolean {
if ( ! formModel . name . trim ( ) ) {
showToast ( "请输入登记事件名称" , "warning" ) ;
return false ;
}
if ( ! formModel . roleCodeList . length ) {
showToast ( "请至少选择一个可登记角色" , "warning" ) ;
return false ;
}
if ( isValueLimitType ( formModel . limitType ) && ! resolveLimitValue ( ) ) {
showToast ( "请输入有效的约束数值" , "warning" ) ;
return false ;
}
const beginAt = resolveTimestamp ( formModel . beginAtText ) ;
const endAt = resolveTimestamp ( formModel . endAtText ) ;
if ( beginAt !== undefined && endAt !== undefined && endAt < beginAt ) {
showToast ( "终止时间不能早于起始时间" , "warning" ) ;
return false ;
}
return true ;
}
@@ -227,15 +303,48 @@ function buildPayload(): RegistrationEvent {
description : formModel . description ,
color : formModel . color ,
status : formModel . status ,
enabled : formModel . enabled ,
requirePhoto : formModel . requirePhoto ,
limitType : formModel . limitType ,
limitValue : resolveLimitValue ( ) ,
beginAt : resolveTimestamp ( formModel . beginAtText ) ,
endAt : resolveTimestamp ( formModel . endAtText ) ,
sort : Math . floor ( Number ( formModel . sortText ) || 0 ) ,
roleCodeList : [ ... formModel . roleCodeList ]
} ;
}
function openBeginAtPicker ( ) : void {
beginAtDraftText . value = formModel . beginAtText || nowDateTimeText . value ;
beginAtPickerVisible . value = true ;
}
function openEndAtPicker ( ) : void {
endAtDraftText . value = formModel . endAtText || nowDateTimeText . value ;
endAtPickerVisible . value = true ;
}
function confirmBeginAt ( ) : void {
formModel . beginAtText = beginAtDraftText . value ;
beginAtPickerVisible . value = false ;
}
function confirmEndAt ( ) : void {
formModel . endAtText = endAtDraftText . value ;
endAtPickerVisible . value = false ;
}
function clearBeginAt ( ) : void {
formModel . beginAtText = "" ;
beginAtDraftText . value = "" ;
beginAtPickerVisible . value = false ;
}
function clearEndAt ( ) : void {
formModel . endAtText = "" ;
endAtDraftText . value = "" ;
endAtPickerVisible . value = false ;
}
async function saveRegistrationEvent ( ) : Promise < void > {
if ( ! validateForm ( ) ) {
return ;
@@ -317,11 +426,12 @@ async function fillForm(): Promise<void> {
name : current . name || "" ,
description : current . description || "" ,
color : current . color || "#2f88ff" ,
status : current . status === "INACTIVE" ? "INACTIVE" : "ACTIVE" ,
enabled : current . enabled ? ? true ,
status : current . status === "DRAFT" ? "DRAFT" : current . status === "INACTIVE" ? "INACTIVE" : "ACTIVE" ,
requirePhoto : current . requirePhoto ? ? false ,
limitType : current . limitType || "NONE" ,
limitValueText : current . limitValue ? String ( current . limitValue ) : "" ,
beginAtText : current . beginAt ? Time . formatDateTime ( new Date ( current . beginAt ) ) : "" ,
endAtText : current . endAt ? Time . formatDateTime ( new Date ( current . endAt ) ) : "" ,
sortText : String ( current . sort ? ? 0 ) ,
roleCodeList : [ ... ( current . roleCodeList || [ ] ) ]
} ) ;
@@ -345,6 +455,12 @@ onMounted(async () => {
border - radius : .75 rem ;
}
. picker - text {
color : # 52607 a ;
width : 100 % ;
text - align : right ;
}
. textarea {
width : 100 % ;
}
@@ -437,6 +553,17 @@ onMounted(async () => {
}
}
. picker - popup {
background : var ( -- td - bg - color - container ) ;
. picker - header {
display : flex ;
padding : .75 rem 1 rem 0 ;
align - items : center ;
justify - content : space - between ;
}
}
. color - popup {
padding : .75 rem 0 1.25 rem ;
background : # fff ;