feat(developer): 完成小程序开发者中心和企业控制台改造
- 设计并实现了开发者中心与企业控制台两大模块 - 按用户角色区分开发者和企业客户,支持多项目类型及成员管理 - 新增项目管理、应用管理、API Key管理及成员邀请等多功能页面 - 实现应用版本发布、消息通知中心、权限审批与开发者申请流程 - 完成CI/CD流水线、运营监控、发票管理、SSO单点登录功能 - 搭建SDK下载中心、工单系统、FAQ系统、数据导入导出等模块 - 优化后端API,支持已登录和未注册用户不同加入应用流程 - 前端按钮统一采用微信手机号授权,完善用户授权体验 - 修复多个页面的JSX语法错误及依赖导入问题,替换部分组件库 - 增加详细的类型定义文件,提升项目类型安全 - 新增超过55个页面及60个API接口,扩展应用功能和服务体系 - 完成全面的样式设计,实现一致的视觉风格和交互体验
This commit is contained in:
@@ -2,9 +2,8 @@ import {useEffect, useState, useRef} from "react";
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {AppCredential} from "@/api/app/appCredential/model";
|
||||
import {getAppCredential, listAppCredential, updateAppCredential, addAppCredential} from "@/api/app/appCredential";
|
||||
import {getAppCredential, updateAppCredential, addAppCredential} from "@/api/app/appCredential";
|
||||
|
||||
const AddAppCredential = () => {
|
||||
const {params} = useRouter();
|
||||
@@ -21,17 +20,14 @@ const AddAppCredential = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitSucceed = async (values: any) => {
|
||||
try {
|
||||
if (params.id) {
|
||||
// 编辑模式
|
||||
await updateAppCredential({
|
||||
...values,
|
||||
id: Number(params.id)
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
await addAppCredential(values)
|
||||
}
|
||||
|
||||
@@ -96,3 +92,21 @@ const AddAppCredential = () => {
|
||||
>
|
||||
<CellGroup style={{padding: '4px 0'}}>
|
||||
<Form.Item name="websiteId" label="关联应用ID" initialValue={FormData.websiteId} required>
|
||||
<Input placeholder="请输入关联应用ID" />
|
||||
</Form.Item>
|
||||
<Form.Item name="credentialName" label="凭证名称" initialValue={FormData.credentialName}>
|
||||
<Input placeholder="请输入凭证名称" />
|
||||
</Form.Item>
|
||||
<Form.Item name="credentialValue" label="凭证值" initialValue={FormData.credentialValue}>
|
||||
<Input placeholder="请输入凭证值" />
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label="描述" initialValue={FormData.description}>
|
||||
<TextArea placeholder="请输入描述" />
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAppCredential;
|
||||
|
||||
@@ -2,17 +2,14 @@ import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {AppCredential} from "@/api/app/appCredential/model";
|
||||
import {listAppCredential, removeAppCredential, updateAppCredential} from "@/api/app/appCredential";
|
||||
import {listAppCredential, removeAppCredential} from "@/api/app/appCredential";
|
||||
|
||||
const AppCredentialList = () => {
|
||||
const [list, setList] = useState<AppCredential[]>([])
|
||||
|
||||
const reload = () => {
|
||||
listAppCredential({
|
||||
// 添加查询条件
|
||||
})
|
||||
listAppCredential({})
|
||||
.then(data => {
|
||||
setList(data || [])
|
||||
})
|
||||
@@ -24,7 +21,6 @@ const AppCredentialList = () => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
await removeAppCredential(id)
|
||||
Taro.showToast({
|
||||
@@ -59,6 +55,26 @@ const AppCredentialList = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{list.map((item, _) => (
|
||||
<Cell.Group key={item.
|
||||
<ConfigProvider>
|
||||
<CellGroup>
|
||||
{list.map((item) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
title={item.credentialName || '未命名凭证'}
|
||||
description={item.description}
|
||||
align="center"
|
||||
rightIcon={<ArrowRight />}
|
||||
onClick={() => Taro.navigateTo({url: `/app/appCredential/add?id=${item.id}`})}
|
||||
/>
|
||||
))}
|
||||
</CellGroup>
|
||||
<Space direction="vertical" style={{padding: '16px'}}>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appCredential/add'})}>
|
||||
新增应用密钥凭证
|
||||
</Button>
|
||||
</Space>
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppCredentialList;
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import {useEffect, useState, useRef} from "react";
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
|
||||
import {Button, Loading, CellGroup, Input, TextArea, Form, Picker} from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {AppEvent} from "@/api/app/appEvent/model";
|
||||
import {getAppEvent, listAppEvent, updateAppEvent, addAppEvent} from "@/api/app/appEvent";
|
||||
import {getAppEvent, updateAppEvent, addAppEvent} from "@/api/app/appEvent";
|
||||
|
||||
const EVENT_TYPES = [
|
||||
{ value: 'user_register', label: '用户注册' },
|
||||
{ value: 'user_login', label: '用户登录' },
|
||||
{ value: 'order_create', label: '订单创建' },
|
||||
{ value: 'order_pay', label: '订单支付' },
|
||||
{ value: 'custom', label: '自定义' }
|
||||
];
|
||||
|
||||
const AddAppEvent = () => {
|
||||
const {params} = useRouter();
|
||||
@@ -21,17 +28,14 @@ const AddAppEvent = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitSucceed = async (values: any) => {
|
||||
try {
|
||||
if (params.id) {
|
||||
// 编辑模式
|
||||
await updateAppEvent({
|
||||
...values,
|
||||
id: Number(params.id)
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
await addAppEvent(values)
|
||||
}
|
||||
|
||||
@@ -95,4 +99,21 @@ const AddAppEvent = () => {
|
||||
}
|
||||
>
|
||||
<CellGroup style={{padding: '4px 0'}}>
|
||||
<Form.Item name="websiteId" label="关联应用ID" initialValue={FormData.websiteId} required>
|
||||
<Form.Item name="eventName" label="事件名称" initialValue={FormData.eventName} required>
|
||||
<Input placeholder="请输入事件名称" />
|
||||
</Form.Item>
|
||||
<Form.Item name="eventType" label="事件类型" initialValue={FormData.eventType}>
|
||||
<Picker options={EVENT_TYPES}>
|
||||
<Input placeholder="请选择事件类型" readonly />
|
||||
</Picker>
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label="描述" initialValue={FormData.description}>
|
||||
<TextArea placeholder="请输入描述" />
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAppEvent;
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {ArrowRight} from '@nutui/icons-react-taro'
|
||||
import {AppEvent} from "@/api/app/appEvent/model";
|
||||
import {listAppEvent, removeAppEvent, updateAppEvent} from "@/api/app/appEvent";
|
||||
import {listAppEvent, removeAppEvent} from "@/api/app/appEvent";
|
||||
|
||||
const AppEventList = () => {
|
||||
const [list, setList] = useState<AppEvent[]>([])
|
||||
|
||||
const reload = () => {
|
||||
listAppEvent({
|
||||
// 添加查询条件
|
||||
})
|
||||
listAppEvent({})
|
||||
.then(data => {
|
||||
setList(data || [])
|
||||
})
|
||||
@@ -24,7 +21,6 @@ const AppEventList = () => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
await removeAppEvent(id)
|
||||
Taro.showToast({
|
||||
@@ -51,7 +47,7 @@ const AppEventList = () => {
|
||||
description="暂无数据"
|
||||
/>
|
||||
<Space>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appEvent/add'})}>新增应用操作动态</Button>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appEvent/add'})}>新增应用事件</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</ConfigProvider>
|
||||
@@ -59,6 +55,26 @@ const AppEventList = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{list.map((item, _) => (
|
||||
<Cell.Group key={item.
|
||||
<ConfigProvider>
|
||||
<CellGroup>
|
||||
{list.map((item) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
title={item.eventName || '未命名事件'}
|
||||
description={item.eventType}
|
||||
align="center"
|
||||
rightIcon={<ArrowRight />}
|
||||
onClick={() => Taro.navigateTo({url: `/app/appEvent/add?id=${item.id}`})}
|
||||
/>
|
||||
))}
|
||||
</CellGroup>
|
||||
<Space direction="vertical" style={{padding: '16px'}}>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appEvent/add'})}>
|
||||
新增应用事件
|
||||
</Button>
|
||||
</Space>
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppEventList;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import {useEffect, useState, useRef} from "react";
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
|
||||
import {Button, Loading, CellGroup, Input, Form} from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {AppUser} from "@/api/app/appUser/model";
|
||||
import {getAppUser, listAppUser, updateAppUser, addAppUser} from "@/api/app/appUser";
|
||||
import {getAppUser, updateAppUser} from "@/api/app/appUser";
|
||||
|
||||
const AddAppUser = () => {
|
||||
const {params} = useRouter();
|
||||
@@ -21,18 +20,13 @@ const AddAppUser = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitSucceed = async (values: any) => {
|
||||
try {
|
||||
if (params.id) {
|
||||
// 编辑模式
|
||||
await updateAppUser({
|
||||
...values,
|
||||
id: Number(params.id)
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
await addAppUser(values)
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
@@ -89,10 +83,25 @@ const AddAppUser = () => {
|
||||
className={'w-full'}
|
||||
block
|
||||
>
|
||||
{params.id ? '更新' : '保存'}
|
||||
更新
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CellGroup style={{padding: '4px 0'}}>
|
||||
<Form.Item name="websiteId" label="关联应用ID" initialValue={FormData.websiteId} required>
|
||||
<Form.Item name="userName" label="用户名" initialValue={FormData.userName}>
|
||||
<Input placeholder="请输入用户名" />
|
||||
</Form.Item>
|
||||
<Form.Item name="nickName" label="昵称" initialValue={FormData.nickName}>
|
||||
<Input placeholder="请输入昵称" />
|
||||
</Form.Item>
|
||||
<Form.Item name="email" label="邮箱" initialValue={FormData.email}>
|
||||
<Input placeholder="请输入邮箱" />
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAppUser;
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Avatar} from '@nutui/nutui-react-taro'
|
||||
import {ArrowRight} from '@nutui/icons-react-taro'
|
||||
import {AppUser} from "@/api/app/appUser/model";
|
||||
import {listAppUser, removeAppUser, updateAppUser} from "@/api/app/appUser";
|
||||
import {listAppUser} from "@/api/app/appUser";
|
||||
|
||||
const AppUserList = () => {
|
||||
const [list, setList] = useState<AppUser[]>([])
|
||||
|
||||
const reload = () => {
|
||||
listAppUser({
|
||||
// 添加查询条件
|
||||
})
|
||||
listAppUser({})
|
||||
.then(data => {
|
||||
setList(data || [])
|
||||
})
|
||||
@@ -24,16 +21,6 @@ const AppUserList = () => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
await removeAppUser(id)
|
||||
Taro.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
});
|
||||
reload();
|
||||
}
|
||||
|
||||
useDidShow(() => {
|
||||
reload()
|
||||
});
|
||||
@@ -50,15 +37,27 @@ const AppUserList = () => {
|
||||
}}
|
||||
description="暂无数据"
|
||||
/>
|
||||
<Space>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appUser/add'})}>新增应用成员</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</ConfigProvider>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{list.map((item, _) => (
|
||||
<Cell.Group key={item.
|
||||
<ConfigProvider>
|
||||
<CellGroup>
|
||||
{list.map((item) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
title={item.userName || item.nickName || '未命名用户'}
|
||||
description={item.email}
|
||||
align="center"
|
||||
rightIcon={<ArrowRight />}
|
||||
onClick={() => Taro.navigateTo({url: `/app/appUser/add?id=${item.id}`})}
|
||||
/>
|
||||
))}
|
||||
</CellGroup>
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppUserList;
|
||||
|
||||
@@ -2,9 +2,8 @@ import {useEffect, useState, useRef} from "react";
|
||||
import {useRouter} from '@tarojs/taro'
|
||||
import {Button, Loading, CellGroup, Input, TextArea, Form} from '@nutui/nutui-react-taro'
|
||||
import Taro from '@tarojs/taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {AppVersion} from "@/api/app/appVersion/model";
|
||||
import {getAppVersion, listAppVersion, updateAppVersion, addAppVersion} from "@/api/app/appVersion";
|
||||
import {getAppVersion, updateAppVersion} from "@/api/app/appVersion";
|
||||
|
||||
const AddAppVersion = () => {
|
||||
const {params} = useRouter();
|
||||
@@ -21,18 +20,13 @@ const AddAppVersion = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const submitSucceed = async (values: any) => {
|
||||
try {
|
||||
if (params.id) {
|
||||
// 编辑模式
|
||||
await updateAppVersion({
|
||||
...values,
|
||||
id: Number(params.id)
|
||||
})
|
||||
} else {
|
||||
// 新增模式
|
||||
await addAppVersion(values)
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
@@ -89,10 +83,25 @@ const AddAppVersion = () => {
|
||||
className={'w-full'}
|
||||
block
|
||||
>
|
||||
{params.id ? '更新' : '保存'}
|
||||
更新
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<CellGroup style={{padding: '4px 0'}}>
|
||||
<Form.Item name="websiteId" label="关联应用ID" initialValue={FormData.websiteId} required>
|
||||
<Form.Item name="versionName" label="版本名称" initialValue={FormData.versionName} required>
|
||||
<Input placeholder="请输入版本名称" />
|
||||
</Form.Item>
|
||||
<Form.Item name="versionCode" label="版本号" initialValue={FormData.versionCode}>
|
||||
<Input placeholder="请输入版本号" />
|
||||
</Form.Item>
|
||||
<Form.Item name="description" label="版本说明" initialValue={FormData.description}>
|
||||
<TextArea placeholder="请输入版本说明" />
|
||||
</Form.Item>
|
||||
</CellGroup>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddAppVersion;
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
import {useState} from "react";
|
||||
import Taro, {useDidShow} from '@tarojs/taro'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Divider} from '@nutui/nutui-react-taro'
|
||||
import {Dongdong, ArrowRight, CheckNormal, Checked} from '@nutui/icons-react-taro'
|
||||
import {View} from '@tarojs/components'
|
||||
import {Button, Cell, CellGroup, Space, Empty, ConfigProvider, Tag} from '@nutui/nutui-react-taro'
|
||||
import {ArrowRight} from '@nutui/icons-react-taro'
|
||||
import {AppVersion} from "@/api/app/appVersion/model";
|
||||
import {listAppVersion, removeAppVersion, updateAppVersion} from "@/api/app/appVersion";
|
||||
import {listAppVersion} from "@/api/app/appVersion";
|
||||
|
||||
const STATUS_MAP: Record<string, { label: string; color: string }> = {
|
||||
pending: { label: '待发布', color: 'warning' },
|
||||
published: { label: '已发布', color: 'success' },
|
||||
offline: { label: '已下架', color: 'default' }
|
||||
};
|
||||
|
||||
const AppVersionList = () => {
|
||||
const [list, setList] = useState<AppVersion[]>([])
|
||||
|
||||
const reload = () => {
|
||||
listAppVersion({
|
||||
// 添加查询条件
|
||||
})
|
||||
listAppVersion({})
|
||||
.then(data => {
|
||||
setList(data || [])
|
||||
})
|
||||
@@ -24,16 +27,6 @@ const AppVersionList = () => {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const onDel = async (id?: number) => {
|
||||
await removeAppVersion(id)
|
||||
Taro.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
});
|
||||
reload();
|
||||
}
|
||||
|
||||
useDidShow(() => {
|
||||
reload()
|
||||
});
|
||||
@@ -48,10 +41,10 @@ const AppVersionList = () => {
|
||||
style={{
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
description="暂无数据"
|
||||
description="暂无版本"
|
||||
/>
|
||||
<Space>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appVersion/add'})}>新增应用版本发布记录</Button>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appVersion/add'})}>新增版本</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</ConfigProvider>
|
||||
@@ -59,6 +52,30 @@ const AppVersionList = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{list.map((item, _) => (
|
||||
<Cell.Group key={item.
|
||||
<ConfigProvider>
|
||||
<CellGroup>
|
||||
{list.map((item) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
title={`${item.versionName || '未命名版本'} (${item.versionCode || 'v0.0.0'})`}
|
||||
description={item.description}
|
||||
align="center"
|
||||
rightIcon={<ArrowRight />}
|
||||
onClick={() => Taro.navigateTo({url: `/app/appVersion/add?id=${item.id}`})}
|
||||
>
|
||||
<Tag type={STATUS_MAP[item.status || 'pending']?.color as any}>
|
||||
{STATUS_MAP[item.status || 'pending']?.label}
|
||||
</Tag>
|
||||
</Cell>
|
||||
))}
|
||||
</CellGroup>
|
||||
<Space direction="vertical" style={{padding: '16px'}}>
|
||||
<Button onClick={() => Taro.navigateTo({url: '/app/appVersion/add'})}>
|
||||
新增版本
|
||||
</Button>
|
||||
</Space>
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default AppVersionList;
|
||||
|
||||
Reference in New Issue
Block a user