Merge remote-tracking branch 'origin/main'

# Conflicts:
#	apps/web-antd/src/views/alert/index.vue
This commit is contained in:
zhongzm
2025-08-13 16:13:50 +08:00
22 changed files with 183 additions and 116 deletions

View File

@@ -21,3 +21,8 @@ VITE_INJECT_APP_LOADING=true
# 打包后是否生成dist.zip # 打包后是否生成dist.zip
VITE_ARCHIVER=true VITE_ARCHIVER=true
# 默认登录用户名
VITE_APP_DEFAULT_USERNAME=
# 默认登录密码
VITE_APP_DEFAULT_PASSWORD=

View File

@@ -18,6 +18,10 @@ export namespace CommentApi {
content?: string; // 评论内容 content?: string; // 评论内容
children?: Comment[]; // 子评论 children?: Comment[]; // 子评论
projectName?: string; // 项目名称 projectName?: string; // 项目名称
status?: string;
serialNo?: string;
businessOwner?: string;
technicalOwnerA?: string;
} }
} }

View File

@@ -22,6 +22,7 @@ export namespace CustomerApi {
projectCount: number; projectCount: number;
licenseCount: number; licenseCount: number;
userCount: number; userCount: number;
contractCount: number;
} }
} }

View File

@@ -20,5 +20,7 @@
"name": "Project Name", "name": "Project Name",
"envInfoFile": "Environment Info Attachment", "envInfoFile": "Environment Info Attachment",
"list": "Project List", "list": "Project List",
"progress": "Progress" "progress": "Comment",
"updateTime": "Last Modified Time",
"commentNum": "Comment Count"
} }

View File

@@ -2,7 +2,7 @@
"project": "项目", "project": "项目",
"operation": "操作", "operation": "操作",
"creationTime": "创建时间", "creationTime": "创建时间",
"remarks": "备注", "remarks": "软件版本信息",
"envInfo": "环境信息", "envInfo": "环境信息",
"status": "项目状态", "status": "项目状态",
"endTime": "项目结束时间", "endTime": "项目结束时间",
@@ -20,5 +20,7 @@
"name": "项目名称", "name": "项目名称",
"envInfoFile": "环境信息附件", "envInfoFile": "环境信息附件",
"list": "项目列表", "list": "项目列表",
"progress": "进展" "progress": "评论",
"updateTime": "最后修改时间",
"commentNum": "评论数"
} }

View File

@@ -1,12 +1,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useAccess } from '@vben/access';
import { Page } from '@vben/common-ui'; import { Page } from '@vben/common-ui';
import { Button, Card, message, Space } from 'ant-design-vue'; import { Button, Card, message, Space } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
import { getAlertPage, updateAlert } from '#/api/alert/alert'; import { getAlertPage, updateAlert } from '#/api/alert/alert';
import { getSimpleUserList } from '#/api/system/user';
const { hasAccessByCodes } = useAccess();
import { getUserPage } from '#/api/system/user'; import { getUserPage } from '#/api/system/user';
import { $t } from '#/locales'; import { $t } from '#/locales';
@@ -49,6 +53,10 @@ const formSchema = computed(() => [
mode: 'multiple', mode: 'multiple',
allowClear: true, allowClear: true,
showSearch: true, showSearch: true,
fieldNames: {
label: 'nickname',
value: 'id',
},
filterOption: (input: string, option: any) => { filterOption: (input: string, option: any) => {
return option?.label?.toLowerCase().includes(input.toLowerCase()); return option?.label?.toLowerCase().includes(input.toLowerCase());
}, },
@@ -140,15 +148,7 @@ function handleReset() {
async function loadUserList() { async function loadUserList() {
try { try {
// 参考部门管理界面的做法使用getUserPage接口 // 参考部门管理界面的做法使用getUserPage接口
const { list } = await getUserPage({ userOptions.value = await getSimpleUserList();
pageNo: 1,
pageSize: 100, // 获取前100个用户
});
userOptions.value = list.map((user) => ({
label: user.nickname || user.username,
value: user.id,
}));
} catch {} } catch {}
} }
@@ -178,14 +178,26 @@ onMounted(async () => {
<template> <template>
<Page auto-content-height> <Page auto-content-height>
<Card :title="$t('alert.alerttitle')"> <Card>
<Form /> <Form />
<div class="mt-4 flex justify-end"> <div class="mt-4 flex justify-end">
<Space> <Space>
<Button type="primary" @click="handleSubmit">{{$t('alert.save')}}</Button> <Button
type="primary"
@click="handleSubmit"
v-if="hasAccessByCodes(['license:alert:update'])"
>
{{$t('alert.save')}}
</Button>
<Button @click="handleReset"> {{ $t('alert.reset') }} </Button> <Button @click="handleReset"> {{ $t('alert.reset') }} </Button>
</Space> </Space>
</div> </div>
<template #title>
<span class="text-lg font-semibold">{{ $t('alert.alerttitle') }} </span>
<a-tooltip title="每天零点发送邮件提醒">
<span class="icon-[mdi--information-outline] text-gray-500"></span>
</a-tooltip>
</template>
</Card> </Card>
</Page> </Page>
</template> </template>

View File

@@ -4,12 +4,6 @@ import type { AnalysisOverviewItem, WorkbenchTrendItem } from '@vben/common-ui';
import { onMounted, shallowRef } from 'vue'; import { onMounted, shallowRef } from 'vue';
import { AnalysisOverview, WorkbenchTrends } from '@vben/common-ui'; import { AnalysisOverview, WorkbenchTrends } from '@vben/common-ui';
import {
SvgBellIcon,
SvgCakeIcon,
SvgCardIcon,
SvgDownloadIcon,
} from '@vben/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime'; import relativeTime from 'dayjs/plugin/relativeTime';
@@ -17,6 +11,8 @@ import relativeTime from 'dayjs/plugin/relativeTime';
import { getLatestCommentList } from '#/api/license/comment'; import { getLatestCommentList } from '#/api/license/comment';
import { dashboard } from '#/api/license/customer'; import { dashboard } from '#/api/license/customer';
import { getLicenseExpiry } from '#/api/license/license'; import { getLicenseExpiry } from '#/api/license/license';
// import { DictTag } from '#/components/dict-tag';
import { DICT_TYPE, getDictObj } from '#/utils';
const overviewItems = shallowRef<AnalysisOverviewItem[]>([]); const overviewItems = shallowRef<AnalysisOverviewItem[]>([]);
const trendItems = shallowRef<WorkbenchTrendItem[]>([]); const trendItems = shallowRef<WorkbenchTrendItem[]>([]);
@@ -28,28 +24,35 @@ onMounted(async () => {
overviewItems.value = [ overviewItems.value = [
{ {
icon: SvgCardIcon, icon: 'icon-[streamline-plump-color--user-pin-flat] size-8 flex-shrink-0',
title: '用户量', title: '用户量',
totalTitle: '总用户量', totalTitle: '总用户量',
totalValue: data.userCount || 0, totalValue: data.userCount || 0,
value: data.userCount || 0, value: data.userCount || 0,
}, },
{ {
icon: SvgCakeIcon, icon: 'icon-[streamline-color--information-desk-customer] size-8 flex-shrink-0',
title: '客户量', title: '客户量',
totalTitle: '总客户量', totalTitle: '总客户量',
totalValue: data?.customerCount || 0, totalValue: data?.customerCount || 0,
value: data?.customerCount || 0, value: data?.customerCount || 0,
}, },
{ {
icon: SvgBellIcon, icon: 'icon-[streamline-sharp-color--laptop-project-screen-flat] size-8 flex-shrink-0',
title: '项目量', title: '项目量',
totalTitle: '总项目量', totalTitle: '总项目量',
totalValue: data?.projectCount || 0, totalValue: data?.projectCount || 0,
value: data?.projectCount || 0, value: data?.projectCount || 0,
}, },
{ {
icon: SvgDownloadIcon, icon: 'icon-[material-icon-theme--folder-contract-open] size-8 flex-shrink-0',
title: '合同量',
totalTitle: '总合同量',
totalValue: data?.contractCount || 0,
value: data?.contractCount || 0,
},
{
icon: 'icon-[streamline-color--key-flat] size-8 flex-shrink-0',
title: 'License量', title: 'License量',
totalTitle: '总License量', totalTitle: '总License量',
totalValue: data?.licenseCount || 0, totalValue: data?.licenseCount || 0,
@@ -61,19 +64,38 @@ onMounted(async () => {
trendItems.value = licenses.map((item) => { trendItems.value = licenses.map((item) => {
return { return {
avatar: '', avatar: '',
content: `客户【<b>${item.customerName}</b>】项目【<b>${item.projectName}</b>】的License将在 <b>${dayjs(item.expiryDate).fromNow(true)}</b> 后到期`, content: `客户【<b>${item.customerName}</b>】项目【<b>${item.projectName}</b>】的License将在 <b>${dayjs(item.expiryDate).fromNow(true)}</b> 后到期`,
date: dayjs(item.expiryDate).format('YYYY-MM-DD HH:mm:ss') || '', date: dayjs(item.expiryDate).format('YYYY-MM-DD HH:mm:ss') || '',
title: item.serialNo || '', title: item.serialNo || '',
status: '',
info: '',
}; };
}); });
const comments = await getLatestCommentList(); const comments = await getLatestCommentList();
projectProgressItems.value = comments.map((item) => { projectProgressItems.value = comments.map((item) => {
// 获取字典对象
const dict = getDictObj(DICT_TYPE.LIC_PROJECT_STATUS, String(item.status));
let dataContent = item.content || '';
if (dataContent) {
const position = dataContent.indexOf('>') + 1;
const originalString = dataContent;
const stringToInsert = `<span style="font-size: 12px; color: #32363973">${item.author}</span>`;
dataContent =
originalString.slice(0, position) +
stringToInsert +
originalString.slice(position);
}
return { return {
avatar: '', avatar: '',
content: item.content || '', content: dataContent,
date: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss') || '', date: dayjs(item.updateTime).format('YYYY-MM-DD HH:mm:ss') || '',
title: item.projectName || '', title: `${item.projectName ?? ''} `,
status: dict,
info: `${item.serialNo ?? ''}&nbsp;&nbsp;${item.businessOwner ?? ''}&nbsp;&nbsp;${item.technicalOwnerA ?? ''}`,
}; };
}); });
}); });
@@ -98,14 +120,14 @@ onMounted(async () => {
<WorkbenchTrends <WorkbenchTrends
:items="trendItems" :items="trendItems"
class="mt-5" class="mt-5"
title="License最先到期" title="License即将到期"
/> />
</div> </div>
<div class="mr-4 w-full lg:w-1/2"> <div class="mr-4 w-full lg:w-1/2">
<WorkbenchTrends <WorkbenchTrends
:items="projectProgressItems" :items="projectProgressItems"
class="mt-5" class="mt-5"
title="项目进展" title="项目评论"
/> />
</div> </div>
</div> </div>

View File

@@ -1,11 +1,9 @@
import type { VbenFormSchema } from '#/adapter/form'; import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { CustomerApi } from '#/api/license/customer'; import type { CustomerApi } from '#/api/license/customer';
import { ref } from 'vue'; import { ref } from 'vue';
import { useAccess } from '@vben/access';
import { z } from '#/adapter/form'; import { z } from '#/adapter/form';
import { import {
isCustomerCodeUnique, isCustomerCodeUnique,
@@ -15,8 +13,6 @@ import { getAreaTree } from '#/api/system/area';
import { $t } from '#/locales'; import { $t } from '#/locales';
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
const { hasAccessByCodes } = useAccess();
export const formData = ref<CustomerApi.Customer>(); export const formData = ref<CustomerApi.Customer>();
/** 新增/修改的表单 */ /** 新增/修改的表单 */
export function useFormSchema(): VbenFormSchema[] { export function useFormSchema(): VbenFormSchema[] {
@@ -193,9 +189,7 @@ export function useGridFormSchema(): VbenFormSchema[] {
} }
/** 列表的字段 */ /** 列表的字段 */
export function useGridColumns( export function useGridColumns(): VxeTableGridOptions<CustomerApi.Customer>['columns'] {
onActionClick?: OnActionClickFn<CustomerApi.Customer>,
): VxeTableGridOptions<CustomerApi.Customer>['columns'] {
return [ return [
{ {
field: 'name', field: 'name',
@@ -258,26 +252,7 @@ export function useGridColumns(
minWidth: 200, minWidth: 200,
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
headerAlign: 'center', slots: { default: 'actions' },
showOverflow: false,
cellRender: {
attrs: {
nameField: 'name',
nameTitle: $t('customer.customer'),
onClick: onActionClick,
},
name: 'CellOperation',
options: [
{
code: 'edit',
show: hasAccessByCodes(['license:customer:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['license:customer:delete']),
},
],
},
}, },
]; ];
} }

View File

@@ -1,8 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { import type { VxeTableGridOptions } from '#/adapter/vxe-table';
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { CustomerApi } from '#/api/license/customer'; import type { CustomerApi } from '#/api/license/customer';
import { Page, useVbenModal } from '@vben/common-ui'; import { Page, useVbenModal } from '@vben/common-ui';
@@ -78,29 +75,12 @@ function handleImport() {
importModalApi.open(); importModalApi.open();
} }
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<CustomerApi.Customer>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
}
const [Grid, gridApi] = useVbenVxeGrid({ const [Grid, gridApi] = useVbenVxeGrid({
formOptions: { formOptions: {
schema: useGridFormSchema(), schema: useGridFormSchema(),
}, },
gridOptions: { gridOptions: {
columns: useGridColumns(onActionClick), columns: useGridColumns(),
height: 'auto', height: 'auto',
pagerConfig: { pagerConfig: {
enabled: true, enabled: true,
@@ -159,12 +139,34 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: $t('ui.actionTitle.import', [$t('customer.customer')]), label: $t('ui.actionTitle.import', [$t('customer.customer')]),
type: 'primary', type: 'primary',
icon: ACTION_ICON.UPLOAD, icon: ACTION_ICON.UPLOAD,
auth: ['license:customer:export'], auth: ['license:customer:import'],
onClick: handleImport, onClick: handleImport,
}, },
]" ]"
/> />
</template> </template>
<template #actions="{ row }">
<TableAction
:actions="[
{
label: $t('common.edit'),
type: 'link',
auth: ['license:customer:update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
type: 'link',
danger: true,
auth: ['license:customer:delete'],
popConfirm: {
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
confirm: onDelete.bind(null, row),
},
},
]"
/>
</template>
</Grid> </Grid>
</Page> </Page>
</template> </template>

View File

@@ -94,7 +94,7 @@ const [Modal, modalApi] = useVbenModal({
</script> </script>
<template> <template>
<Modal :title="getTitle" class="w-[800px]"> <Modal :title="getTitle" class="w-1/2">
<Form class="mx-4" /> <Form class="mx-4" />
</Modal> </Modal>
</template> </template>

View File

@@ -172,7 +172,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: $t('license.applyAction', ['License']), label: $t('license.applyAction', ['License']),
type: 'primary', type: 'primary',
icon: ACTION_ICON.ADD, icon: ACTION_ICON.ADD,
auth: ['license:license:create'], auth: ['license:license:apply'],
onClick: onCreate, onClick: onCreate,
}, },
{ {
@@ -186,7 +186,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: $t('ui.actionTitle.import', ['License']), label: $t('ui.actionTitle.import', ['License']),
type: 'primary', type: 'primary',
icon: ACTION_ICON.UPLOAD, icon: ACTION_ICON.UPLOAD,
auth: ['license:license:export'], auth: ['license:license:import'],
onClick: handleImport, onClick: handleImport,
}, },
]" ]"
@@ -199,6 +199,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
{ {
label: $t('license.detail'), label: $t('license.detail'),
type: 'link', type: 'link',
auth: ['license:license:query'],
onClick: onDetail.bind(null, row), onClick: onDetail.bind(null, row),
}, },
{ {
@@ -231,7 +232,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: $t('license.reapply'), label: $t('license.reapply'),
type: 'link', type: 'link',
ifShow: row.status === 3, ifShow: row.status === 3,
auth: ['license:license:query'], auth: ['license:license:reapply'],
onClick: onReapply.bind(null, row), onClick: onReapply.bind(null, row),
}, },
{ {

View File

@@ -83,8 +83,8 @@ const formatContent = computed(() => {
</a-avatar> </a-avatar>
</template> </template>
<template #datetime> <template #datetime>
<a-tooltip :title="dayjs(data.updateTime).format('YYYY-MM-DD HH:mm:ss')"> <a-tooltip :title="dayjs(data.updateTime)">
<span>{{ dayjs(data.updateTime).fromNow() }}</span> <span>{{ dayjs(data.updateTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</a-tooltip> </a-tooltip>
</template> </template>
<template #content> <template #content>

View File

@@ -21,6 +21,33 @@ const sortByTime = () => {
isSortAsc.value = !isSortAsc.value; isSortAsc.value = !isSortAsc.value;
emit('getCommentByProjectId', props.projectId, isSortAsc.value); emit('getCommentByProjectId', props.projectId, isSortAsc.value);
}; };
function countNodes(tree: CommentApi.Comment) {
if (tree === null) {
return 0;
}
let count = 1; // 当前节点
if (!tree.children || tree.children.length === 0 || (tree?.depth ?? 0) > 1) {
return count; // 如果没有子节点,直接返回当前节点数量
}
for (let i = 0; i < tree.children.length; i++) {
if (tree.children[i] !== undefined) {
count += countNodes(tree.children[i] as CommentApi.Comment); // 递归计算子节点的数量
}
}
return count;
}
function getCommentCount(comments?: CommentApi.Comment[]) {
if (!comments || comments.length === 0) {
return 0;
}
let count = 0;
for (const comment of comments) {
count += countNodes(comment);
}
return count;
}
</script> </script>
<template> <template>
<div id="article-comment" style="padding: 5px"> <div id="article-comment" style="padding: 5px">
@@ -30,7 +57,7 @@ const sortByTime = () => {
{{ $t('comment.hotComment') }} {{ $t('comment.hotComment') }}
</span> </span>
<span style="padding: 0 15px 0 5px; color: #9499a0">{{ <span style="padding: 0 15px 0 5px; color: #9499a0">{{
comments?.length ?? 0 getCommentCount(comments)
}}</span> }}</span>
</span> </span>
<span <span

View File

@@ -102,6 +102,7 @@ export function useFormSchema(): VbenFormSchema[] {
label: $t('project.contractCode'), label: $t('project.contractCode'),
rules: 'required', rules: 'required',
component: 'Input', component: 'Input',
help: '没有合同的项目请填0',
}, },
{ {
fieldName: 'businessStatus', fieldName: 'businessStatus',
@@ -183,6 +184,7 @@ export function useFormSchema(): VbenFormSchema[] {
fieldName: 'remark', fieldName: 'remark',
label: $t('project.remarks'), label: $t('project.remarks'),
component: 'Textarea', component: 'Textarea',
rules: 'required',
formItemClass: 'col-span-2', formItemClass: 'col-span-2',
}, },
]; ];
@@ -422,11 +424,22 @@ export function useGridColumns(
visible: false, visible: false,
minWidth: 120, minWidth: 120,
}, },
{
field: 'commentNum',
title: $t('project.commentNum'),
minWidth: 70,
},
{
field: 'updateTime',
title: $t('project.updateTime'),
minWidth: 130,
sortable: true,
formatter: 'formatDateTime',
},
{ {
field: 'createTime', field: 'createTime',
title: $t('project.creationTime'), title: $t('project.creationTime'),
// visible: false, minWidth: 130,
minWidth: 120,
formatter: 'formatDateTime', formatter: 'formatDateTime',
}, },
{ {
@@ -452,7 +465,7 @@ export function useGridColumns(
{ {
code: 'progress', code: 'progress',
text: $t('project.progress'), text: $t('project.progress'),
show: hasAccessByCodes(['license:project:update']), show: hasAccessByCodes(['license:project:comment']),
}, },
{ {
code: 'delete', code: 'delete',

View File

@@ -174,7 +174,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: $t('ui.actionTitle.import', [$t('project.project')]), label: $t('ui.actionTitle.import', [$t('project.project')]),
type: 'primary', type: 'primary',
icon: ACTION_ICON.UPLOAD, icon: ACTION_ICON.UPLOAD,
auth: ['license:project:export'], auth: ['license:project:import'],
onClick: handleImport, onClick: handleImport,
}, },
]" ]"

View File

@@ -31,7 +31,7 @@ const [Form, formApi] = useVbenForm({
class: 'w-full', class: 'w-full',
}, },
// formItemClass: 'col-span-2', // formItemClass: 'col-span-2',
labelWidth: 80, labelWidth: 100,
}, },
layout: 'horizontal', layout: 'horizontal',
schema: useFormSchema(), schema: useFormSchema(),
@@ -90,7 +90,7 @@ const [Modal, modalApi] = useVbenModal({
</script> </script>
<template> <template>
<Modal :title="getTitle" class="w-[800px]"> <Modal :title="getTitle" class="w-1/2">
<Form class="mx-4" /> <Form class="mx-4" />
</Modal> </Modal>
</template> </template>

View File

@@ -8,7 +8,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
VbenCountToAnimator, VbenCountToAnimator,
VbenIcon,
} from '@vben-core/shadcn-ui'; } from '@vben-core/shadcn-ui';
interface Props { interface Props {
@@ -25,7 +24,7 @@ withDefaults(defineProps<Props>(), {
</script> </script>
<template> <template>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4"> <div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-5">
<template v-for="item in items" :key="item.title"> <template v-for="item in items" :key="item.title">
<Card :title="item.title" class="w-full"> <Card :title="item.title" class="w-full">
<CardHeader> <CardHeader>
@@ -39,7 +38,8 @@ withDefaults(defineProps<Props>(), {
class="text-xl" class="text-xl"
prefix="" prefix=""
/> />
<VbenIcon :icon="item.icon" class="size-8 flex-shrink-0" /> <!-- <VbenIcon :icon="item.icon" class="size-8 flex-shrink-0" /> -->
<span :class="item.icon"></span>
</CardContent> </CardContent>
<CardFooter class="justify-between"> <CardFooter class="justify-between">
<span>{{ item.totalTitle }}</span> <span>{{ item.totalTitle }}</span>

View File

@@ -23,6 +23,8 @@ interface WorkbenchTrendItem {
content: string; content: string;
date: string; date: string;
title: string; title: string;
status: any;
info: string;
} }
interface WorkbenchTodoItem { interface WorkbenchTodoItem {

View File

@@ -43,7 +43,22 @@ withDefaults(defineProps<Props>(), {
/> />
<div class="min-w-0 flex-auto"> <div class="min-w-0 flex-auto">
<p class="text-foreground text-sm font-semibold leading-6"> <p class="text-foreground text-sm font-semibold leading-6">
{{ item.title }} <span
class="text-foreground mr-2 text-sm font-semibold leading-6"
>{{ item.title }}
</span>
<a-tag
v-if="item.status"
:color="
item.status.colorType
? item.status.colorType
: item.status.cssClass
"
>
{{ item.status.label }}
</a-tag>
<!-- eslint-disable vue/no-v-html -->
<span v-html="item.info"></span>
</p> </p>
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<p <p

View File

@@ -10,7 +10,7 @@
"password": "Password", "password": "Password",
"nickname": "Nickname", "nickname": "Nickname",
"tenant": "Tenant", "tenant": "Tenant",
"usernameTip": "Please enter username", "usernameTip": "Please enter username or email",
"passwordErrorTip": "Password is incorrect", "passwordErrorTip": "Password is incorrect",
"passwordTip": "Please enter password", "passwordTip": "Please enter password",
"nicknameTip": "Please enter nickname", "nicknameTip": "Please enter nickname",

View File

@@ -10,7 +10,7 @@
"password": "密码", "password": "密码",
"nickname": "昵称", "nickname": "昵称",
"tenant": "租户", "tenant": "租户",
"usernameTip": "请输入用户名", "usernameTip": "请输入用户名或邮箱",
"passwordTip": "请输入密码", "passwordTip": "请输入密码",
"nicknameTip": "请输入昵称", "nicknameTip": "请输入昵称",
"tenantTip": "请选择租户", "tenantTip": "请选择租户",

View File

@@ -8,18 +8,6 @@
"name": "@vben/web-antd", "name": "@vben/web-antd",
"path": "apps/web-antd", "path": "apps/web-antd",
}, },
{
"name": "@vben/web-ele",
"path": "apps/web-ele",
},
{
"name": "@vben/web-naive",
"path": "apps/web-naive",
},
{
"name": "@vben/docs",
"path": "docs",
},
{ {
"name": "@vben/commitlint-config", "name": "@vben/commitlint-config",
"path": "internal/lint-configs/commitlint-config", "path": "internal/lint-configs/commitlint-config",
@@ -156,10 +144,6 @@
"name": "@vben/utils", "name": "@vben/utils",
"path": "packages/utils", "path": "packages/utils",
}, },
{
"name": "@vben/playground",
"path": "playground",
},
{ {
"name": "@vben/turbo-run", "name": "@vben/turbo-run",
"path": "scripts/turbo-run", "path": "scripts/turbo-run",