diff --git a/public/template_example.html b/public/template_example.html deleted file mode 100644 index fcbeed4..0000000 --- a/public/template_example.html +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - -
标题文字
- - - - - - - - - - -
产品卖点描述
- - - - -
- - - 免责声明文字 - -
- -
- - - - - - - - - diff --git a/src/api/settings/workflow/session.ts b/src/api/settings/workflow/session.ts index fc44074..01fb2e9 100644 --- a/src/api/settings/workflow/session.ts +++ b/src/api/settings/workflow/session.ts @@ -24,6 +24,8 @@ export interface VOSessionInfoResult { totalTokens: number; totalFee: number; errorMsg: string; + // 失败详细原因(工作流节点失败详情,如「执行工作流失败: ...节点:生成视频, 失败原因:...」),比 errorMsg 更具体 + error?: string; createdAt: string; } diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts index f4115f7..9fc36dd 100644 --- a/src/api/system/user/index.ts +++ b/src/api/system/user/index.ts @@ -70,6 +70,22 @@ export function deleteUser(ids: number[]) { }); } +export function recharge(data: object) { + return request({ + url: '/shop-user-trade/account/controller/recharge', + method: 'post', + data: data, + }); +} + +export function getWalletLogs(userId: number, pageNum: number, pageSize: number) { + return request({ + url: '/shop-user-trade/account/controller/logs', + method: 'get', + params: { userId, pageNum, pageSize }, + }); +} + export function checkIsSuperAdmin() { return request({ url: '/admin-go/api/v1/system/user/checkIsSuperAdmin', diff --git a/src/api/trade/pricing/index.ts b/src/api/trade/pricing/index.ts new file mode 100644 index 0000000..6fe2117 --- /dev/null +++ b/src/api/trade/pricing/index.ts @@ -0,0 +1,44 @@ +import request from '/@/utils/request'; + +/** 计价对象枚举 */ +export function getSubjects() { + return request({ + url: '/shop-user-trade/pricing/controller/subjects', + method: 'get', + }); +} + +/** 计价配置详情 */ +export function getPricingConfig(params: { subjectType: string; subjectId: string }) { + return request({ + url: '/shop-user-trade/pricing/controller/config/get', + method: 'get', + params, + }); +} + +/** 计价对象可选计费方式(workflow/business 使用;model 计价方式由配置规则决定,不调用) */ +export function getChargeModes(params: { subjectType: string; subjectId: string }) { + return request({ + url: '/shop-user-trade/pricing/controller/subjects/charge-modes', + method: 'get', + params, + }); +} + +/** 新增/更新计价配置(id > 0 更新,0 新增;rules 传费率对象;id 兼容雪花字符串避免精度丢失) */ +export function savePricingConfig(data: { + id: string | number; + subjectType: string; + subjectId: string; + rules: object; + minBalance?: number; + currency?: string; + enabled?: number; +}) { + return request({ + url: '/shop-user-trade/pricing/controller/config/save', + method: 'post', + data, + }); +} diff --git a/src/components/patchTemplate/PatchTemplateEditor.vue b/src/components/patchTemplate/PatchTemplateEditor.vue index 5cb1723..60f8131 100644 --- a/src/components/patchTemplate/PatchTemplateEditor.vue +++ b/src/components/patchTemplate/PatchTemplateEditor.vue @@ -166,7 +166,7 @@ function nextImageKey(template: PatchTemplate): string | null { return null; } -const DEFAULT_TEMPLATE_URL = 'https://cdn.redpowerfuture.com/tenantid-1/template_example1.html'; +const DEFAULT_TEMPLATE_URL = 'https://cdn.redpowerfuture.com/tenantid-1/vertical_template_example.html'; const props = defineProps<{ modelValue: PatchTemplate[]; @@ -290,14 +290,24 @@ const handleImageUpload = async (templateIndex: number, imgIdx: number, file: an } }; -// 下载参考模板文件 -const handleDownload = (_e?: Event) => { - const a = document.createElement('a'); - a.href = '/template_example.html'; - a.download = 'template_example.html'; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); +// 下载参考模板文件:统一走 CDN,转 blob 触发下载(避免跨域 直接打开页面) +const handleDownload = async (_e?: Event) => { + try { + const res = await fetch(DEFAULT_TEMPLATE_URL); + if (!res.ok) throw new Error('参考模板获取失败'); + const blob = await res.blob(); + const fileName = decodeURIComponent(DEFAULT_TEMPLATE_URL.split('/').pop() || 'vertical_template_example.html'); + const blobUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = blobUrl; + a.download = fileName; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(blobUrl); + } catch (error: any) { + ElMessage.error(error?.message || '参考模板下载失败'); + } }; diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue index 01419d6..9dfa370 100644 --- a/src/layout/navBars/breadcrumb/user.vue +++ b/src/layout/navBars/breadcrumb/user.vue @@ -203,11 +203,12 @@ export default defineComponent({ } }, }) - .then(async () => { + .then(() => { // 手动退出登录也只清理登录态缓存,保留主题、语言等本地配置。 Session.clearAuth(); - // 显式回到登录页,避免保留之前受保护页面的重定向参数 - await router.replace('/login'); + // 整页跳转登录页(刷新重建路由实例):SPA 内 router.replace 不会重置已注册的动态路由, + // 重新登录时 setAddRoute 的 hasRoute 判断会跳过新菜单注册,出现"菜单显示但点击 404"(如价格管理页) + window.location.href = import.meta.env.BASE_URL + '#/login'; }) .catch(() => {}); } else if (path === 'wareHouse') { diff --git a/src/theme/other.scss b/src/theme/other.scss index 9995a55..abcd4e7 100644 --- a/src/theme/other.scss +++ b/src/theme/other.scss @@ -31,6 +31,10 @@ color: #f56c6c !important; } +.op-btn-recharge { + color: #67c23a !important; // 充值 绿色 +} + [data-theme='dark'] { // textarea - css vars --w-e-textarea-bg-color: var(--el-color-white) !important; @@ -49,6 +53,10 @@ color: #f56c6c !important; // 删除 红色 } + .op-btn-recharge { + color: #67c23a !important; // 充值 绿色 + } + // toolbar - css vars --w-e-toolbar-color: var(--el-text-color-primary) !important; --w-e-toolbar-bg-color: var(--el-color-white) !important; diff --git a/src/views/home/components/WorkflowFormCard.vue b/src/views/home/components/WorkflowFormCard.vue index 2f06165..fe80a65 100644 --- a/src/views/home/components/WorkflowFormCard.vue +++ b/src/views/home/components/WorkflowFormCard.vue @@ -33,6 +33,12 @@
+ + + + + + @@ -162,6 +183,8 @@ import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentIns import { ElMessageBox, ElMessage, ElTree, FormInstance } from 'element-plus'; import { Search } from '@element-plus/icons-vue'; import EditUser from '/@/views/system/user/component/editUser.vue'; +import RechargeUser from '/@/views/system/user/component/rechargeUser.vue'; +import WalletLog from '/@/views/system/user/component/walletLog.vue'; import { getUserList, getDeptTree, resetUserPwd, changeUserStatus, deleteUser } from '/@/api/system/user/index'; interface TableDataState { @@ -186,11 +209,13 @@ interface TableDataState { export default defineComponent({ name: 'systemUser', - components: { EditUser }, + components: { EditUser, RechargeUser, WalletLog }, setup() { const { proxy } = getCurrentInstance(); const { sys_user_sex } = proxy.useDict('sys_user_sex'); const editUserRef = ref(); + const rechargeUserRef = ref(); + const walletLogRef = ref(); const queryRef = ref(); const filterText = ref(''); const treeRef = ref>(); @@ -259,6 +284,14 @@ export default defineComponent({ const onOpenEditUser = (row: any) => { editUserRef.value.openDialog(row); }; + // 打开充值弹窗 + const onOpenRecharge = (row: any) => { + rechargeUserRef.value.openDialog(row); + }; + // 打开流水信息弹窗 + const onOpenWalletLog = (row: any) => { + walletLogRef.value.openDialog(row.id); + }; // 删除用户 const onRowDel = (row: any) => { let msg = '你确定要删除所选用户?'; @@ -358,8 +391,12 @@ export default defineComponent({ return { queryRef, editUserRef, + rechargeUserRef, + walletLogRef, onOpenAddUser, onOpenEditUser, + onOpenRecharge, + onOpenWalletLog, onRowDel, onHandleSizeChange, onHandleCurrentChange,