系列文章
【Vue】vue增加导航标签
本文链接:https://blog.csdn.net/youcheng_ge/article/details/134965353
【Vue】Element开发笔记
本文链接:https://blog.csdn.net/youcheng_ge/article/details/133947977
【Vue】vue,在Windows IIS平台部署
本文链接:https://blog.csdn.net/youcheng_ge/article/details/133859117
【Vue】vue2与WebApi跨域CORS问题
本文链接:https://blog.csdn.net/youcheng_ge/article/details/133808959
【Vue】nvm安装教程(解决npm下依赖包版本冲突)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/132896207
【Vue】vue开发环境搭建教程(详细)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/132689006
【Vue】日期格式化(全局)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/135017332
【Vue】elementUI表格,导出Excel
本文链接:https://blog.csdn.net/youcheng_ge/article/details/135018489
【Vue】el-date-picker日期范围组件(本周、本月、上周)
本文链接:https://blog.csdn.net/youcheng_ge/article/details/135088143
【前端】前后端通信方法与差异
本文链接:https://blog.csdn.net/youcheng_ge/article/details/135153985
文章目录
- 系列文章
- 前言
- 一、技术介绍
- 二、项目源码
-
- [2.1 api功能方法](#2.1 api功能方法)
- [2.2 langs多语言(语言翻译)](#2.2 langs多语言(语言翻译))
- [2.3 router路由(菜单)](#2.3 router路由(菜单))
- [2.4 views视图(前端页面)](#2.4 views视图(前端页面))
- 三、效果展示
- 四、资源链接
前言
本专栏为 前端【Vue】专栏,主要介绍Vue知识点。对于刚进入计算机世界的学生来说,学习课本上的知识是远远不够的,并且国内教材偏旧,所以需要我们通过互联网自主学习。
这里普及一个知识:HTML已不仅仅只能开发 Web,也可以开发移动端(Android、iOS),所以本专栏也会介绍 移动端的开发。
我个人将移动端开发,分为两大方向:
①原生开发
最早一批,使用安卓开发工具包(Android SDK)和Java语言来开发App的方式。原生开发允许开发者充分利用安卓平台的功能和特性,以及庞大的安卓开发社区资源。但缺点就是门槛高、需要适配不同尺寸的屏幕、测试繁琐,对开发人员技术要求高。
②混合开发(加壳方式)当前热门,使用Web技术(
网页三剑客HTML、CSS和JavaScript)开发App的方式,使用vue.js、node.js、Angular.js、React.js、api.js等框架开发。混合开发具有较高的开发效率和跨平台的优势,由于使用Web技术进行 界面渲染样式丰富、屏幕适配(栅格技术自适应)效果好。但缺点就是对底层硬件调用库尚不完善,有时候会发生异常,对框架依赖较高,不过库在不断完善中,主要的相机、相册、GPS、存储调用是没有问题的。
Vue是前端开发中的一个分支,它基于标准 HTML、CSS 和 JavaScript 构建,学习Vue不可以速成,得先熟悉网页三剑客(HTML、CSS和JavaScript)。Vue是一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。

一、技术介绍
切换到根目录
bash
cd mms_client
项目初始化
bash
pnpm install
项目启动项
bash
npm run dev:antd
二、项目源码
2.1 api功能方法
文件名: index.ts
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\api\basic-data\index.ts
代码:
ts
export * from './tax-0001';
export * from './tax-0003';
export * from './tax-0004';
export * from './tax-0006';
export * from './tax-0007';
export * from './tax-0008';
export * from './tax-0009';
export * from './tax-0010';
export * from './tax-0012';
export * from './tax-0020';
export * from './tax-0400';
export * from './tax-0410';
export * from './tax-2036';
export * from './tax-2037';
export * from './tax-0140';
export * from './tpa-1020';
export * from './tqa-0101';
export * from './tqa-0110';
export * from './tqa-1102';
export * from './ts-position';
文件名: tax-2036.ts
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\api\basic-data\tax-2036.ts
代码:
ts
import type { Recordable } from '@vben/types';
import { requestClient } from '#/api/request';
export namespace Tax2036Api {
export interface Tax2036 {
[key: string]: any;
id: number;
cPlantId: string;
cStoreHouse: string;
cStoLocation: string;
cStoType: string;
cTlDj?: null | string;
cStoLocationTxt?: null | string;
cRemark?: null | string;
cIsUse: string;
creationTime: string;
lastModificationTime?: string;
}
export interface CreateUpdateTax2036Dto {
cPlantId: string;
cStoreHouse: string;
cStoLocation: string;
cStoType: string;
cTlDj?: null | string;
cStoLocationTxt?: null | string;
cRemark?: null | string;
cIsUse: string;
}
export interface PagedResultDto<T> {
items: T[];
totalCount: number;
}
}
const apiUrl = '/api/app/t-aX_2036';
async function getTax2036List(params: Recordable<any>) {
return requestClient.get<Tax2036Api.PagedResultDto<Tax2036Api.Tax2036>>(
apiUrl,
{
params,
},
);
}
async function getTax2036ById(id: number) {
return requestClient.get<Tax2036Api.Tax2036>(`${apiUrl}/${id}`);
}
async function createTax2036(data: Tax2036Api.CreateUpdateTax2036Dto) {
return requestClient.post<Tax2036Api.Tax2036>(apiUrl, data);
}
async function updateTax2036(
id: number,
data: Tax2036Api.CreateUpdateTax2036Dto,
) {
return requestClient.put<Tax2036Api.Tax2036>(`${apiUrl}/${id}`, data);
}
async function deleteTax2036(id: number) {
return requestClient.delete(`${apiUrl}/${id}`);
}
export {
createTax2036,
deleteTax2036,
getTax2036ById,
getTax2036List,
updateTax2036,
};
2.2 langs多语言(语言翻译)
文件名: mes.json
路径(英文):
E:\MyProject\mms\mms_client\apps\web-antd\src\locales\langs\en-US\mes.json
代码:
json
"tax2036": {
"title": "Storage Location Master Data",
"list": "Storage Location Master Data List",
"name": "Storage Location",
"operation": "Operation",
"loading": "Loading {0} ...",
"isUsing": "Include Disabled Data",
"cPlantId": "Plant",
"cStoreHouse": "Store House Code",
"cStoLocation": "Storage Location",
"cStoType": "Storage Type",
"cTlDj": "Feeding Consumption Freeze Flag",
"cStoLocationTxt": "Storage Location Description",
"cRemark": "Remark",
"cIsUse": "Available"
},
路径(中文):
E:\MyProject\mms\mms_client\apps\web-antd\src\locales\langs\zh-CN\mes.json
代码:
json
"tax2036": {
"title": "仓位基础数据维护",
"list": "仓位基础数据维护列表",
"name": "仓位",
"operation": "操作",
"loading": "正在加载 {0} ...",
"isUsing": "查询禁用数据",
"cPlantId": "实体工厂",
"cStoreHouse": "实体库代码",
"cStoLocation": "仓位",
"cStoType": "仓储类型",
"cTlDj": "投料耗用冻结标记",
"cStoLocationTxt": "仓位描述",
"cRemark": "备注",
"cIsUse": "是否启用"
},
2.3 router路由(菜单)
**文件名:**mes.ts
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\router\routes\modules\mes.ts
代码
ts
{
component: () =>
import('#/views/mes/basic-data/tax-2036/list.vue'),
meta: {
icon: 'lucide:map-pin',
title: $t('mes.basicData.tax2036.title'),
},
name: 'Tax2036Management',
path: '/mes/basic-data/tax-2036',
},
2.4 views视图(前端页面)
文件名: form.vue
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\views\mes\basic-data\tax-2036\modules\form.vue
代码
vue
<script lang="ts" setup>
import type { Tax2036Api } from '#/api';
import { computed, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { Button } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { createTax2036, updateTax2036 } from '#/api';
import { $t } from '#/locales';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<Tax2036Api.Tax2036>();
const defaultValues: Tax2036Api.CreateUpdateTax2036Dto = {
cIsUse: 'Y',
cPlantId: '',
cStoLocation: '',
cStoType: '',
cStoreHouse: '',
};
const getTitle = computed(() => {
return formData.value?.id
? $t('ui.actionTitle.edit', [$t('mes.basicData.tax2036.name')])
: $t('ui.actionTitle.create', [$t('mes.basicData.tax2036.name')]);
});
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
},
layout: 'vertical',
schema: useFormSchema(),
showDefaultActions: false,
wrapperClass: 'grid-cols-1 md:grid-cols-2',
});
function normalizeFormValues(values: Record<string, any>) {
return {
...defaultValues,
...values,
} as Tax2036Api.CreateUpdateTax2036Dto;
}
function resetForm() {
formApi.resetForm();
formApi.setValues(formData.value || defaultValues);
}
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
const { valid } = await formApi.validate();
if (!valid) return;
const values = normalizeFormValues(await formApi.getValues());
modalApi.lock();
try {
await (formData.value?.id
? updateTax2036(formData.value.id, values)
: createTax2036(values));
modalApi.close();
emit('success');
} finally {
modalApi.lock(false);
}
},
async onOpenChange(isOpen) {
if (isOpen) {
const data = modalApi.getData<Tax2036Api.Tax2036>();
formData.value = data?.id ? data : undefined;
formApi.setState({ schema: useFormSchema(!!formData.value?.id) });
formApi.resetForm();
await new Promise((resolve) => setTimeout(resolve, 100));
formApi.setValues(formData.value || defaultValues);
}
},
});
</script>
<template>
<Modal :title="getTitle">
<div class="max-h-[70vh] overflow-y-auto px-1">
<Form class="mx-4" />
</div>
<template #prepend-footer>
<div class="flex-auto">
<Button type="primary" danger @click="resetForm">
{{ $t('common.reset') }}
</Button>
</div>
</template>
</Modal>
</template>
文件名: data.ts
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\views\mes\basic-data\tax-2036\data.ts
代码:
ts
import type { VbenFormSchema } from '#/adapter/form';
import type { OnActionClickFn, VxeTableGridColumns } from '#/adapter/vxe-table';
import type { Tax0004Api, Tax2036Api } from '#/api';
import { getPopupContainer } from '@vben/utils';
import { getTax0004List } from '#/api';
import { $t } from '#/locales';
async function getPlantOptions() {
const result = await getTax0004List({
MaxResultCount: 1000,
SkipCount: 0,
});
return (result.items || []).map((plant: Tax0004Api.Tax0004) => ({
label: `${plant.cPlantId} - ${plant.cPlantNm}`,
value: plant.cPlantId,
}));
}
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
component: 'ApiSelect',
componentProps: {
allowClear: true,
api: getPlantOptions,
class: 'w-full',
getPopupContainer,
optionFilterProp: 'label',
showSearch: true,
},
fieldName: 'cPlantId',
label: $t('mes.basicData.tax2036.cPlantId'),
},
{
component: 'Input',
fieldName: 'cStoreHouse',
label: $t('mes.basicData.tax2036.cStoreHouse'),
},
{
component: 'Input',
fieldName: 'cStoLocation',
label: $t('mes.basicData.tax2036.cStoLocation'),
},
{
component: 'Input',
fieldName: 'cStoType',
label: $t('mes.basicData.tax2036.cStoType'),
},
{
component: 'Checkbox',
defaultValue: false,
fieldName: 'includeInvalidData',
hideLabel: true,
renderComponentContent: () => ({
default: $t('mes.basicData.tax2036.isUsing'),
}),
},
];
}
export function useFormSchema(readonlyCode = false): VbenFormSchema[] {
return [
{
component: 'ApiSelect',
componentProps: {
allowClear: true,
api: getPlantOptions,
class: 'w-full',
getPopupContainer,
optionFilterProp: 'label',
showSearch: true,
},
fieldName: 'cPlantId',
label: $t('mes.basicData.tax2036.cPlantId'),
rules: 'required',
},
{
component: 'Input',
fieldName: 'cStoreHouse',
label: $t('mes.basicData.tax2036.cStoreHouse'),
rules: 'required',
},
{
component: 'Input',
componentProps: {
readonly: readonlyCode,
},
fieldName: 'cStoLocation',
label: $t('mes.basicData.tax2036.cStoLocation'),
rules: 'required',
},
{
component: 'Input',
fieldName: 'cStoType',
label: $t('mes.basicData.tax2036.cStoType'),
rules: 'required',
},
{
component: 'Input',
fieldName: 'cTlDj',
label: $t('mes.basicData.tax2036.cTlDj'),
},
{
component: 'Input',
fieldName: 'cStoLocationTxt',
label: $t('mes.basicData.tax2036.cStoLocationTxt'),
},
{
component: 'Input',
defaultValue: 'Y',
fieldName: 'cIsUse',
label: $t('mes.basicData.tax2036.cIsUse'),
rules: 'required',
},
{
component: 'Textarea',
componentProps: {
rows: 3,
},
fieldName: 'cRemark',
formItemClass: 'md:col-span-2',
label: $t('mes.basicData.tax2036.cRemark'),
},
];
}
export function useColumns<T = Tax2036Api.Tax2036>(
onActionClick: OnActionClickFn<T>,
): VxeTableGridColumns {
return [
{
field: 'cPlantId',
minWidth: 160,
title: $t('mes.basicData.tax2036.cPlantId'),
},
{
field: 'cStoreHouse',
minWidth: 160,
title: $t('mes.basicData.tax2036.cStoreHouse'),
},
{
field: 'cStoLocation',
minWidth: 140,
title: $t('mes.basicData.tax2036.cStoLocation'),
},
{
field: 'cStoType',
minWidth: 140,
title: $t('mes.basicData.tax2036.cStoType'),
},
{
field: 'cTlDj',
minWidth: 150,
title: $t('mes.basicData.tax2036.cTlDj'),
},
{
field: 'cStoLocationTxt',
minWidth: 180,
title: $t('mes.basicData.tax2036.cStoLocationTxt'),
},
{
field: 'cIsUse',
minWidth: 100,
title: $t('mes.basicData.tax2036.cIsUse'),
},
{
field: 'cRemark',
minWidth: 180,
title: $t('mes.basicData.tax2036.cRemark'),
},
{
field: 'creationTime',
formatter: ({ cellValue }: { cellValue: string }) => {
if (!cellValue) return '-';
return new Date(cellValue).toLocaleString();
},
minWidth: 180,
title: $t('common.createTime'),
},
{
align: 'center',
cellRender: {
attrs: {
nameField: 'cStoLocation',
nameTitle: $t('mes.basicData.tax2036.name'),
onClick: onActionClick,
},
name: 'CellOperation',
},
field: 'operation',
fixed: 'right',
title: $t('mes.basicData.tax2036.operation'),
width: 130,
},
];
}
文件名: list.vue
路径: E:\MyProject\mms\mms_client\apps\web-antd\src\views\mes\basic-data\tax-2036\list.vue
代码:
vue
<script lang="ts" setup>
import type {
OnActionClickParams,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { Tax2036Api } from '#/api';
import { Page, useVbenModal } from '@vben/common-ui';
import { Plus } from '@vben/icons';
import { Button, message } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
deleteTax2036,
getTax2036ById,
getTax2036List,
} from '#/api';
import { $t } from '#/locales';
import { useColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
const [FormModal, formModalApi] = useVbenModal({
centered: true,
class: 'w-[920px]',
connectedComponent: Form,
destroyOnClose: true,
fullscreenButton: false,
});
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: useGridFormSchema(),
submitOnChange: true,
},
gridOptions: {
columns: useColumns(onActionClick),
height: 'auto',
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
const params: Record<string, any> = {
MaxResultCount: page.pageSize,
SkipCount: (page.currentPage - 1) * page.pageSize,
};
if (formValues.cPlantId) {
params.CPlantId = formValues.cPlantId;
}
if (formValues.cStoreHouse) {
params.CStoreHouse = formValues.cStoreHouse;
}
if (formValues.cStoLocation) {
params.CStoLocation = formValues.cStoLocation;
}
if (formValues.cStoType) {
params.CStoType = formValues.cStoType;
}
params.IncludeInvalidData = formValues.includeInvalidData === true;
const result = await getTax2036List(params);
return {
items: result.items || [],
total: result.totalCount || 0,
};
},
},
},
rowConfig: {
keyField: 'id',
},
toolbarConfig: {
custom: true,
export: false,
refresh: true,
search: true,
zoom: true,
},
} as VxeTableGridOptions<Tax2036Api.Tax2036>,
});
function onActionClick(e: OnActionClickParams<Tax2036Api.Tax2036>) {
switch (e.code) {
case 'delete': {
onDelete(e.row);
break;
}
case 'edit': {
onEdit(e.row);
break;
}
}
}
async function onEdit(row: Tax2036Api.Tax2036) {
const hideLoading = message.loading({
content: $t('mes.basicData.tax2036.loading', [row.cStoLocation]),
duration: 0,
key: 'action_process_msg',
});
try {
const data = await getTax2036ById(row.id);
formModalApi.setData(data).open();
hideLoading();
} catch {
hideLoading();
}
}
function onDelete(row: Tax2036Api.Tax2036) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.cStoLocation]),
duration: 0,
key: 'action_process_msg',
});
deleteTax2036(row.id)
.then(() => {
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.cStoLocation]),
key: 'action_process_msg',
});
onRefresh();
})
.catch(() => {
hideLoading();
});
}
function onRefresh() {
gridApi.query();
}
function onCreate() {
formModalApi.setData(null).open();
}
</script>
<template>
<Page auto-content-height>
<FormModal @success="onRefresh" />
<Grid :table-title="$t('mes.basicData.tax2036.list')">
<template #toolbar-tools>
<Button type="primary" @click="onCreate">
<Plus class="size-5" />
{{ $t('ui.actionTitle.create', [$t('mes.basicData.tax2036.name')]) }}
</Button>
</template>
</Grid>
</Page>
</template>
三、效果展示


