Merge branch 'dev_vite' of http://18.167.251.121:10003/aidlab/aida_front into dev_vite

This commit is contained in:
李志鹏
2026-01-08 14:29:12 +08:00
10 changed files with 135 additions and 66 deletions

View File

@@ -18,7 +18,7 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>{{ $t('admin.UserName') }}:</span> <span>{{ $t('admin.UserName') }}:</span>
<SelectUser v-model:value="ids" multiple /> <SelectUser v-model:value="ids" multiple valueKey="label" labelKey="email" />
</div> </div>
</div> </div>
<div class="admin_search"> <div class="admin_search">

View File

@@ -36,18 +36,9 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>{{ $t("admin.Email") }}:</span> <span>{{ $t("admin.Email") }}:</span>
<input <SelectUser v-model="email" labelKey="email" valueKey="email" />
v-model="email"
:placeholder="$t('admin.enterEmail')"
@keydown.enter="gettrialList"
type="text"
style="width: 250px"
/>
</div>
<div class="admin_state_item">
<span>{{ $t("admin.UserName") }}:</span>
<SelectUser v-model="ids" multiple />
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>Organization Name:</span> <span>Organization Name:</span>
<input <input
@@ -239,7 +230,7 @@
endTime: endDate, endTime: endDate,
startTime: startDate, startTime: startDate,
ids: ids, ids: ids,
email: this.email.trim(), email: this.email?.trim(),
organizationName: this.organizationName, organizationName: this.organizationName,
}; };
Https.axiosGet(Https.httpUrls.getDesignStatistic, { Https.axiosGet(Https.httpUrls.getDesignStatistic, {

View File

@@ -220,7 +220,7 @@ export default defineComponent({
changeEvent:this.changeEvent, changeEvent:this.changeEvent,
size:this.pageSize, size:this.pageSize,
page:this.currentPage, page:this.currentPage,
email:this.email.trim(), email:this.email?.trim(),
} }
Https.axiosPost(Https.httpUrls.getGenerateFrequency,data).then((rv: any) => { Https.axiosPost(Https.httpUrls.getGenerateFrequency,data).then((rv: any) => {
if (rv) { if (rv) {

View File

@@ -25,15 +25,7 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>{{ $t('admin.UserName') }}:</span> <span>{{ $t('admin.UserName') }}:</span>
<a-select <SelectUser v-model="userIdList" labelKey="email" multiple />
v-model:value="userIdList"
mode="multiple"
style="width: 280px"
:filter-option="filterOption"
:placeholder="$t('admin.selectUserName')"
max-tag-count="responsive"
:options="dataList"
></a-select>
</div> </div>
</div> </div>
@@ -78,8 +70,10 @@ import { LabelLayout } from 'echarts/features';
import { useStore } from "vuex"; import { useStore } from "vuex";
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import SelectUser from '@/component/common/SelectUser.vue'
export default defineComponent({ export default defineComponent({
components: { components: {
SelectUser
}, },
setup() { setup() {
const {t} = useI18n() const {t} = useI18n()

View File

@@ -32,18 +32,16 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>Email:</span> <span>Email:</span>
<input <!-- <input
v-model="email" v-model="email"
placeholder="Please enter email" placeholder="Please enter email"
@keydown.enter="gettrialList" @keydown.enter="gettrialList"
type="text" type="text"
style="width: 250px" style="width: 250px"
/> /> -->
</div> <SelectUser v-model="email" labelKey="email" valueKey="email" />
<div class="admin_state_item">
<span>User Name:</span>
<SelectUser v-model="ids" multiple />
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>Organization Name:</span> <span>Organization Name:</span>
<input <input
@@ -302,7 +300,7 @@
endTime: endDate, endTime: endDate,
startTime: startDate, startTime: startDate,
ids: ids, ids: ids,
email: this.email.trim(), email: this.email?.trim(),
organizationName: this.organizationName, organizationName: this.organizationName,
}; };
Https.axiosGet(Https.httpUrls.getDesignStatistic, { Https.axiosGet(Https.httpUrls.getDesignStatistic, {

View File

@@ -423,7 +423,7 @@ export default defineComponent({
page: filterData.currentPage, page: filterData.currentPage,
systemUser: filterData.systemUser, systemUser: filterData.systemUser,
country: filterData.country, country: filterData.country,
email: filterData.email.trim(), email: filterData.email?.trim(),
userType: filterData.userType, userType: filterData.userType,
ids: filterData.ids, ids: filterData.ids,
occupation: filterData.occupation, occupation: filterData.occupation,

View File

@@ -25,16 +25,7 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>User:</span> <span>User:</span>
<!-- <a-select <SelectUser v-model="userIdList" labelKey="email" multiple />
v-model:value="userIdList"
mode="multiple"
style="width: 280px"
:filter-option="filterOption"
placeholder="Select Item..."
max-tag-count="responsive"
:options="dataList"
></a-select> -->
<SelectUser v-model="userIdList" multiple />
</div> </div>
</div> </div>

View File

@@ -11,13 +11,13 @@
<a-form-item label="ID"> <a-form-item label="ID">
<a-input v-model:value="searchForm.id" allow-clear placeholder="Input the id" /> <a-input v-model:value="searchForm.id" allow-clear placeholder="Input the id" />
</a-form-item> </a-form-item>
<a-form-item label="Name"> <!-- <a-form-item label="Name">
<a-input <a-input
v-model:value="searchForm.name" v-model:value="searchForm.name"
allow-clear allow-clear
placeholder="Input the name" placeholder="Input the name"
/> />
</a-form-item> </a-form-item> -->
<a-form-item label="Time Range"> <a-form-item label="Time Range">
<a-range-picker <a-range-picker
v-model:value="searchForm.dateRange" v-model:value="searchForm.dateRange"
@@ -245,7 +245,7 @@
Admin Account: Admin Account:
<span>*</span> <span>*</span>
</span> </span>
<SelectUser v-model="formState.adminAccId" labelKey="email" /> <SelectUser ref="userRef" v-model="formState.adminAccId" labelKey="email" />
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span> <span>
@@ -255,6 +255,7 @@
<a-date-picker <a-date-picker
v-model:value="formState.currentPeriodStart" v-model:value="formState.currentPeriodStart"
value-format="X" value-format="X"
:disabled="isEditMode && formState.status !== 'PENDING'"
style="width: 250px" style="width: 250px"
:disabledDate="disabledDate" :disabledDate="disabledDate"
:show-time="{ format: 'HH:mm' }" :show-time="{ format: 'HH:mm' }"
@@ -275,7 +276,9 @@
v-model:value="formState.currentPeriodEnd" v-model:value="formState.currentPeriodEnd"
value-format="X" value-format="X"
:show-time="{ format: 'HH:mm' }" :show-time="{ format: 'HH:mm' }"
:disabledDate="disabledDate" :disabledDate="disableEndDate"
:disabledTime="disableEndTime"
:show-now="!isEditMode"
style="width: 250px" style="width: 250px"
class="range_picker" class="range_picker"
placeholder="Select the end time" placeholder="Select the end time"
@@ -403,8 +406,6 @@ import type { FormInstance, Rule } from 'ant-design-vue/es/form'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import dayjs, { Dayjs } from 'dayjs' import dayjs, { Dayjs } from 'dayjs'
const testuser = ref('')
type PlanStatus = 'PENDING' | 'ACTIVE' | 'EXPIRED' type PlanStatus = 'PENDING' | 'ACTIVE' | 'EXPIRED'
interface SubscriptionPlan { interface SubscriptionPlan {
id: number id: number
@@ -420,11 +421,8 @@ interface SubscriptionPlan {
endStamp: number endStamp: number
} }
const disabledDate = (current: Dayjs) => {
return current && current < dayjs().subtract(1, 'days').endOf('day')
}
const countryList = ref([]) const countryList = ref([])
const userRef = ref(null)
const searchForm = reactive({ const searchForm = reactive({
name: '', name: '',
@@ -493,6 +491,64 @@ const statusOption = ref([
} }
]) ])
const disabledDate = (current: Dayjs) => {
return current && current < dayjs().subtract(1, 'days').endOf('day')
}
const disableEndDate = (current: Dayjs) => {
if (isEditMode.value) {
const specificTime = dayjs(formState.currentPeriodEnd)
return current && current < dayjs(formState.currentPeriodEnd * 1000).startOf('day')
}
return disabledDate(current)
}
const range = (start: number, end: number) => {
const result = []
for (let i = start; i < end; i++) {
result.push(i)
}
return result
}
const disableEndTime = date => {
if (!formState.currentPeriodEnd || !isEditMode.value)
return {
disabledHours: () => [],
disabledMinutes: () => [],
disabledSeconds: () => []
}
const specificTime = dayjs.unix(formState.currentPeriodEnd)
if (date && date.isSame(specificTime, 'day')) {
// 如果是指定日期当天,禁用时间戳之前的时间
const hour = specificTime.hour()
const minute = specificTime.minute()
const second = specificTime.second()
return {
disabledHours: () => Array.from({ length: hour }, (_, i) => i), // 禁用小时之前
disabledMinutes: selectedHour => {
if (selectedHour === hour) {
return Array.from({ length: minute }, (_, i) => i) // 同小时,禁用分钟之前
}
return []
},
disabledSeconds: (selectedHour, selectedMinute) => {
if (selectedHour === hour && selectedMinute === minute) {
return Array.from({ length: second }, (_, i) => i) // 同小时分钟,禁用秒之前
}
return []
}
}
}
return {
disabledHours: () => [],
disabledMinutes: () => [],
disabledSeconds: () => []
}
}
const normalizeStatus = (status?: string): PlanStatus | undefined => { const normalizeStatus = (status?: string): PlanStatus | undefined => {
if (!status) return undefined if (!status) return undefined
const upper = status.toUpperCase() as PlanStatus const upper = status.toUpperCase() as PlanStatus
@@ -527,6 +583,14 @@ const columns = [
width: 120, width: 120,
ellipsis: true ellipsis: true
}, },
{
title: 'Country or Region',
dataIndex: 'countryOrRegion',
key: 'countryOrRegion',
align: 'center',
width: 120,
ellipsis: true
},
{ {
title: 'Start Time', title: 'Start Time',
dataIndex: 'currentPeriodStart', dataIndex: 'currentPeriodStart',
@@ -626,7 +690,7 @@ const handleReset = () => {
searchForm.adminAccId = undefined searchForm.adminAccId = undefined
searchForm.status = [] searchForm.status = []
searchForm.id = '' searchForm.id = ''
searchForm.countryOrRegion = '' searchForm.countryOrRegion = null
handleSearch() handleSearch()
} }
@@ -649,6 +713,7 @@ const openEdit = (record: SubscriptionPlan) => {
formState.accountNum = (record as any).accountNum || null formState.accountNum = (record as any).accountNum || null
formState.status = record.status formState.status = record.status
formState.id = record.id formState.id = record.id
formState.countryOrRegion = (record as any).countryOrRegion || null
// 检查组织ID是否在已加载的组织列表中如果不在则添加临时项 // 检查组织ID是否在已加载的组织列表中如果不在则添加临时项
if (record.organizationId) { if (record.organizationId) {
@@ -658,7 +723,6 @@ const openEdit = (record: SubscriptionPlan) => {
String(org.id) === String(record.organizationId) String(org.id) === String(record.organizationId)
) )
if (!orgExists) { if (!orgExists) {
// 从表格数据中获取组织名称,如果存在则添加临时项
const orgName = (record as any).organizationName const orgName = (record as any).organizationName
if (orgName) { if (orgName) {
organizationOptions.value = [ organizationOptions.value = [
@@ -671,8 +735,16 @@ const openEdit = (record: SubscriptionPlan) => {
} }
} }
} }
modalVisible.value = true modalVisible.value = true
if (record.adminAccId) {
nextTick(() => {
userRef.value.patchList({
label: record.name,
value: record.adminAccId,
email: record.adminAccEmail
})
})
}
} }
const validateForm = (): boolean => { const validateForm = (): boolean => {

View File

@@ -37,17 +37,7 @@
</div> </div>
<div class="admin_state_item"> <div class="admin_state_item">
<span>Email:</span> <span>Email:</span>
<input <SelectUser v-model="email" labelKey="email" valueKey="email" />
v-model="email"
placeholder="Please enter email"
@keydown.enter="gettrialList"
type="text"
style="width: 250px"
/>
</div>
<div class="admin_state_item">
<span>User Name:</span>
<SelectUser v-model="ids" multiple />
</div> </div>
</div> </div>
<div class="admin_search"> <div class="admin_search">

View File

@@ -18,7 +18,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, reactive } from 'vue' import { computed, ref, reactive ,defineExpose} from 'vue'
import { debounce } from 'lodash-es' import { debounce } from 'lodash-es'
import { Https } from '@/tool/https' import { Https } from '@/tool/https'
import { useStore } from '@/store' import { useStore } from '@/store'
@@ -94,6 +94,21 @@ const doFetch = async (reset = false) => {
}) })
const data = res?.data const data = res?.data
pager.hasMore = res?.hasMore pager.hasMore = res?.hasMore
if (tempItem.value.value) {
const exists = data.find(
it =>
(props.valueKey ? it[props.valueKey] : it.value) ===
(props.valueKey ? tempItem.value[props.valueKey] : tempItem.value.value)
)
if (!!exists) {
// 如果存在,用data中的新数据覆盖internalList中的旧数据
const index = internalList.value.indexOf(tempItem.value)
const existsIndex = data.indexOf(exists)
internalList.value[index] = { ...exists }
data.splice(existsIndex, 1)
tempItem.value = {}
}
}
if (pager.page === 1) internalList.value = data if (pager.page === 1) internalList.value = data
else internalList.value = internalList.value.concat(data) else internalList.value = internalList.value.concat(data)
pager.page += 1 pager.page += 1
@@ -129,6 +144,24 @@ const handleFocus = () => {
const onChange = (val: any) => { const onChange = (val: any) => {
emit('change', val) emit('change', val)
} }
// 解决回显时没有加载对应选项的问题
const tempItem = ref({})
const patchList = item => {
const exists = internalList.value.find(
it =>
(props.valueKey ? it[props.valueKey] : it.value) ===
(props.valueKey ? item[props.valueKey] : item.value)
)
if (!exists) {
internalList.value.unshift({ ...item, temp: true })
tempItem.value = item
}
}
defineExpose({
patchList
})
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped></style>