feat: 订阅计划页面
This commit is contained in:
@@ -32,7 +32,12 @@
|
|||||||
placeholder="Select Organization"
|
placeholder="Select Organization"
|
||||||
style="width: 180px"
|
style="width: 180px"
|
||||||
@popupScroll="handleOrganizationScroll"
|
@popupScroll="handleOrganizationScroll"
|
||||||
|
@select="handleOrganizationSelect"
|
||||||
|
@change="handleOrganizationChange"
|
||||||
>
|
>
|
||||||
|
<a-select-option value="ADD_ORGANIZATION" class="add-organization-option">
|
||||||
|
+ 添加组织
|
||||||
|
</a-select-option>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="item in organizationOptions"
|
v-for="item in organizationOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -193,8 +198,13 @@
|
|||||||
allow-clear
|
allow-clear
|
||||||
style="width: 250px"
|
style="width: 250px"
|
||||||
@popupScroll="handleOrganizationScroll"
|
@popupScroll="handleOrganizationScroll"
|
||||||
|
@select="handleOrganizationSelect"
|
||||||
|
@change="handleOrganizationChange"
|
||||||
:disabled="isEditMode"
|
:disabled="isEditMode"
|
||||||
>
|
>
|
||||||
|
<a-select-option value="ADD_ORGANIZATION" class="add-organization-option">
|
||||||
|
+ 添加组织
|
||||||
|
</a-select-option>
|
||||||
<a-select-option
|
<a-select-option
|
||||||
v-for="item in organizationOptions"
|
v-for="item in organizationOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -284,11 +294,66 @@
|
|||||||
<div class="admin_search_item" @click="handleSubmit">OK</div>
|
<div class="admin_search_item" @click="handleSubmit">OK</div>
|
||||||
</div>
|
</div>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
|
<div class="organizationModal" ref="organizationModal"></div>
|
||||||
|
<a-modal
|
||||||
|
class="organization_modal"
|
||||||
|
v-model:visible="organizationModalVisible"
|
||||||
|
:footer="null"
|
||||||
|
:get-container="() => $refs.organizationModal"
|
||||||
|
:maskClosable="false"
|
||||||
|
:centered="true"
|
||||||
|
:mask="true"
|
||||||
|
wrapClassName="#app"
|
||||||
|
:keyboard="false"
|
||||||
|
destroy-on-close
|
||||||
|
>
|
||||||
|
<div class="modal_title_text">
|
||||||
|
<div>Create Organization</div>
|
||||||
|
</div>
|
||||||
|
<div class="subscriptionPlan_center admin_page">
|
||||||
|
<div class="form_content">
|
||||||
|
<div class="admin_state_item">
|
||||||
|
<span>
|
||||||
|
Name:
|
||||||
|
<span>*</span>
|
||||||
|
</span>
|
||||||
|
<a-input
|
||||||
|
v-model:value="organizationForm.name"
|
||||||
|
placeholder="Input the name"
|
||||||
|
style="width: 250px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="admin_state_item">
|
||||||
|
<span>
|
||||||
|
Type:
|
||||||
|
<span>*</span>
|
||||||
|
</span>
|
||||||
|
<a-select
|
||||||
|
v-model:value="organizationForm.type"
|
||||||
|
placeholder="Select type"
|
||||||
|
style="width: 250px"
|
||||||
|
>
|
||||||
|
<a-select-option value="Enterprise">Enterprise</a-select-option>
|
||||||
|
<a-select-option value="Education">Education</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="organization_footer">
|
||||||
|
<div class="footer_btn ant-btn ant-btn-primary" @click="cancelOrganizationModal">
|
||||||
|
Close
|
||||||
|
</div>
|
||||||
|
<div class="footer_btn ant-btn ant-btn-primary" @click="handleCreateOrganization">
|
||||||
|
OK
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, ref, onMounted, computed } from 'vue'
|
import { reactive, ref, onMounted, computed, nextTick } from 'vue'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import { Https } from '@/tool/https'
|
import { Https } from '@/tool/https'
|
||||||
import { formatTime } from '@/tool/util'
|
import { formatTime } from '@/tool/util'
|
||||||
@@ -341,6 +406,12 @@ const formState = reactive({
|
|||||||
accountNum: null as number | null
|
accountNum: null as number | null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const organizationModalVisible = ref(false)
|
||||||
|
const organizationForm = reactive({
|
||||||
|
name: '',
|
||||||
|
type: undefined as string | undefined
|
||||||
|
})
|
||||||
|
|
||||||
const statusLabelMap: Record<PlanStatus, string> = {
|
const statusLabelMap: Record<PlanStatus, string> = {
|
||||||
active: 'Active',
|
active: 'Active',
|
||||||
paused: 'Paused',
|
paused: 'Paused',
|
||||||
@@ -580,6 +651,72 @@ const handleOrganizationScroll = (e: any) => {
|
|||||||
getOrganizationList(true)
|
getOrganizationList(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleOrganizationSelect = (value: string) => {
|
||||||
|
if (value === 'ADD_ORGANIZATION') {
|
||||||
|
// 打开添加组织弹窗
|
||||||
|
organizationModalVisible.value = true
|
||||||
|
// 使用nextTick确保值被重置,使其不被选中
|
||||||
|
nextTick(() => {
|
||||||
|
if (searchForm.organizationId === 'ADD_ORGANIZATION') {
|
||||||
|
searchForm.organizationId = undefined
|
||||||
|
}
|
||||||
|
if (formState.organizationId === 'ADD_ORGANIZATION') {
|
||||||
|
formState.organizationId = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOrganizationChange = (value: string) => {
|
||||||
|
// 如果change事件触发时值是"添加组织",立即重置
|
||||||
|
if (value === 'ADD_ORGANIZATION') {
|
||||||
|
nextTick(() => {
|
||||||
|
if (searchForm.organizationId === 'ADD_ORGANIZATION') {
|
||||||
|
searchForm.organizationId = undefined
|
||||||
|
}
|
||||||
|
if (formState.organizationId === 'ADD_ORGANIZATION') {
|
||||||
|
formState.organizationId = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelOrganizationModal = () => {
|
||||||
|
organizationModalVisible.value = false
|
||||||
|
organizationForm.name = ''
|
||||||
|
organizationForm.type = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCreateOrganization = async () => {
|
||||||
|
if (!organizationForm.name || !organizationForm.type) {
|
||||||
|
message.warning('Please fill in name and type')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res: any = await Https.axiosGet(Https.httpUrls.addOrganization, {
|
||||||
|
params: {
|
||||||
|
name: organizationForm.name,
|
||||||
|
type: organizationForm.type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
message.success('Organization created successfully')
|
||||||
|
cancelOrganizationModal()
|
||||||
|
// 刷新组织列表
|
||||||
|
await getOrganizationList()
|
||||||
|
// 如果是在编辑/新建弹窗中,自动选择新创建的组织
|
||||||
|
if (modalVisible.value) {
|
||||||
|
const newOrgId = res?.id || res?.data?.id || res
|
||||||
|
if (newOrgId) {
|
||||||
|
formState.organizationId = String(newOrgId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
message.error(error.message || 'Failed to create organization')
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const filterOption = (input: string, option: any) => {
|
const filterOption = (input: string, option: any) => {
|
||||||
const label = option?.label ?? option?.children ?? option?.key?.label ?? ''
|
const label = option?.label ?? option?.children ?? option?.key?.label ?? ''
|
||||||
return String(label).toLowerCase().includes(input.toLowerCase())
|
return String(label).toLowerCase().includes(input.toLowerCase())
|
||||||
@@ -612,9 +749,6 @@ const filterOption = (input: string, option: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
:deep(.subscriptionPlan_modal) {
|
:deep(.subscriptionPlan_modal) {
|
||||||
.ant-modal-body {
|
.ant-modal-body {
|
||||||
height: calc(65rem * 1.2);
|
height: calc(65rem * 1.2);
|
||||||
@@ -666,4 +800,49 @@ const filterOption = (input: string, option: any) => {
|
|||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.ant-select-dropdown) {
|
||||||
|
.add-organization-option {
|
||||||
|
color: #1890ff !important;
|
||||||
|
font-weight: 600;
|
||||||
|
background-color: #f0f7ff !important;
|
||||||
|
border-bottom: 1px solid #e6f4ff;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e6f4ff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.organization_modal) {
|
||||||
|
.ant-modal-body {
|
||||||
|
height: auto;
|
||||||
|
min-height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 2rem 2.5rem;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscriptionPlan_center {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
overflow: visible;
|
||||||
|
padding: 1rem 0;
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal_title_text {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.organization_footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
column-gap: 3rem;
|
||||||
|
.footer_btn {
|
||||||
|
border-radius: 3.3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user