feat(ui): web移动端初始化

This commit is contained in:
廖彦棋
2024-03-13 17:30:24 +08:00
parent fcd86fbebd
commit 5f371bdc4a
277 changed files with 50840 additions and 668 deletions

View File

@@ -0,0 +1,92 @@
<script lang="ts" setup>
import SearchTable from "@/components/SearchTable/SearchTable.vue";
import type { SearchTableColumns } from "@/components/SearchTable/type";
import { getList, save as saveApi, deletApi, resetPassword } from "./api";
import UserForm from "./UserForm.vue";
import { Message } from "@arco-design/web-vue";
import { dateFormat } from "@chatgpt-plus/packages/utils";
import UserPassword from "./UserPassword.vue";
import useCustomFormPopup from "@/composables/useCustomFormPopup";
const columns: SearchTableColumns[] = [
{
title: "账号",
dataIndex: "username",
search: {
valueType: "input",
},
},
{
title: "剩余对话次数",
dataIndex: "calls",
},
{
title: "剩余绘图次数",
dataIndex: "img_calls",
},
{
title: "累计消耗tokens",
dataIndex: "total_tokens",
},
{
title: "状态",
dataIndex: "status",
render: ({ record }) => {
return record.status ? "正常" : "停用";
},
},
{
title: "过期时间",
dataIndex: "expired_time",
width: 180,
render: ({ record }) => {
return dateFormat(record.expired_time);
},
},
{
title: "注册时间",
dataIndex: "created_at",
width: 180,
render: ({ record }) => {
return dateFormat(record.created_at);
},
},
{
title: "操作",
slotName: "actions",
width: 180,
fixed: "right",
},
];
//弹窗
const editModal = useCustomFormPopup(UserForm, saveApi, {
popupProps: (arg) => ({ title: arg[0].record ? "编辑用户" : "新增用户" }),
});
const password = useCustomFormPopup(UserPassword, resetPassword, {
popupProps: (arg) => ({ title: "重置密码" }),
});
const handleDelete = async ({ id }: { id: string }, reload) => {
const res = await deletApi(id);
if (res.code === 0) {
Message.success("操作成功");
reload();
}
};
</script>
<template>
<SearchTable :request="getList" :columns="columns">
<template #actions="{ record, reload }">
<a-link @click="editModal({ record, reload })">编辑</a-link>
<a-popconfirm content="确定删除?" @ok="handleDelete(record, reload)">
<a-link status="danger">删除</a-link>
</a-popconfirm>
<a-link @click="password({ record, reload })">重置密码</a-link>
</template>
<template #search-extra="{ reload }">
<a-button @click="editModal({ reload })" size="small" type="primary">
<template #icon> <icon-plus /> </template>新增
</a-button>
</template>
</SearchTable>
</template>

View File

@@ -0,0 +1,112 @@
<template>
<a-form ref="formRef" :model="form" :style="{ width: '600px' }" @submit="handleSubmit">
<a-form-item
field="username"
label="账号"
:rules="[{ required: true, message: '请输入账号' }]"
:validate-trigger="['change', 'input']"
>
<a-input v-model="form.username" placeholder="请输入账号" />
</a-form-item>
<a-form-item
v-if="!props.data.id"
field="password"
label="密码"
:rules="[{ required: true, message: '请输入密码' }]"
:validate-trigger="['change', 'input']"
showable
>
<a-input v-model="form.password" placeholder="请输入密码" />
</a-form-item>
<a-form-item
field="calls"
label="对话次数"
:rules="[{ required: true, message: '请输入对话次数' }]"
>
<a-input-number v-model="form.calls" placeholder="请输入对话次数" />
</a-form-item>
<a-form-item
field="img_calls"
label="绘图次数"
:rules="[{ required: true, message: '请输入绘图次数' }]"
>
<a-input-number v-model="form.img_calls" placeholder="请输入绘图次数" />
</a-form-item>
<a-form-item field="expired_time" label="有效期">
<a-date-picker v-model="form.expired_time" placeholder="请选择有效期" />
</a-form-item>
<a-form-item field="chat_roles" label="聊天角色">
<a-select
:field-names="{ value: 'key', label: 'name' }"
v-model="form.chat_roles"
placeholder="请选择聊天角色"
multiple
:options="roleOption"
:rules="[{ required: true, message: '请选择聊天角色' }]"
>
</a-select>
</a-form-item>
<a-form-item field="chat_models" label="模型角色">
<a-select
:field-names="{ value: 'value', label: 'name' }"
v-model="form.chat_models"
placeholder="请选择模型角色"
multiple
:options="modalOption"
:rules="[{ required: true, message: '请选择模型角色' }]"
>
</a-select>
</a-form-item>
<a-form-item field="status" label="启用状态">
<a-switch v-model="form.status" />
</a-form-item>
<a-form-item field="vip" label="开通VIP">
<a-switch v-model="form.vip" />
</a-form-item>
</a-form>
</template>
<script setup>
import { ref, defineExpose, defineProps } from "vue";
import { getModel, getRole } from "./api";
const props = defineProps({
data: {},
});
const formRef = ref();
const form = ref({
username: "",
password: "",
calls: "",
img_calls: "",
expired_time: "",
chat_roles: [],
chat_models: [],
status: false,
vip: false,
});
if (props.data?.id) {
form.value = Object.assign({}, props.data);
if (form.value.expired_time === 0) {
form.value.expired_time = "";
}
}
//拿选项
const modalOption = ref([]);
const roleOption = ref([]);
const getOption = (api, container) => {
api().then(({ code, data }) => {
if (code === 0) {
container.value = data;
}
});
};
getOption(getModel, modalOption);
getOption(getRole, roleOption);
defineExpose({
formRef,
form,
});
</script>

View File

@@ -0,0 +1,44 @@
<template>
<a-form ref="formRef" :model="form" :style="{ width: '600px' }" @submit="handleSubmit">
<a-form-item
field="username"
label="账号"
:rules="[{ required: true, message: 'name is required' }]"
:validate-trigger="['change', 'input']"
:disabled="true"
>
<a-input v-model="form.username" placeholder="请输入账号" />
</a-form-item>
<a-form-item
field="password"
label="新密码"
:rules="[{ required: true, message: 'password is required' }]"
:validate-trigger="['change', 'input']"
showable
>
<a-input v-model="form.password" placeholder="请输入密码" />
</a-form-item>
</a-form>
</template>
<script setup>
import { ref, defineExpose, defineProps } from "vue";
import { getModel, getRole } from "./api";
const props = defineProps({
data: {},
});
const formRef = ref();
const form = ref({
id: "",
username: "",
password: "",
});
form.value.id = props.data.id;
form.value.username = props.data.username;
defineExpose({
formRef,
form,
});
</script>

View File

@@ -0,0 +1,47 @@
import http from "@/http/config";
export const getList = (params?: Record<string, unknown>) => {
return http({
url: "/api/admin/user/list",
method: "get",
params,
});
};
export const save = (data?: Record<string, unknown>) => {
return http({
url: "/api/admin/user/save",
method: "post",
data,
});
};
export const deletApi = (id: string | number) => {
return http({
url: `/api/admin/user/remove`,
method: "post",
data: { id }
});
};
export const getRole = () => {
return http({
url: `/api/admin/role/list`,
method: "get",
});
};
export const getModel = () => {
return http({
url: `/api/admin/model/list`,
method: "get",
});
};
export const resetPassword = (data) => {
return http({
url: `/api/admin/user/resetPass`,
method: "post",
data,
});
};