【愚公系列】2023年02月 WMS智能仓储系统-015.基础设置(货主信息、运费设置、客户信息)

news/2024/11/9 5:11:41/

文章目录

  • 前言
  • 一、基础设置
    • 1.货主信息
      • 1.1 页面代码
      • 1.2 接口代码
    • 2.运费设置
      • 2.1 页面代码
      • 2.2 接口代码
    • 3.客户信息
      • 3.1 页面代码
      • 3.2 接口代码


前言

基础设置主要分为以下几个模块:

  • 首页
  • 公司信息
  • 角色设置
  • 菜单设置
  • 用户管理
  • 商品类别设置
  • 商品管理
  • 供应商信息
  • 仓库设置
  • 货主信息
  • 运费设置
  • 客户信息

在这里插入图片描述
这边需要提下客户和货主的概念:客户是与仓储签订直接合同的甲方,货主是拥有货权的人。

实际情况下,货主会委托某人或某企业管理自己的货物,而这个管理人或企业会与仓储签订合同,使用仓储的软硬件资源。

货主是客户的甲方,客户是仓储的甲方(货主和客户也可能是同一人或企业)。

一、基础设置

1.货主信息

在这里插入图片描述

1.1 页面代码

1、主页面代码

<template><div class="container"><div><!-- Main Content --><v-card class="mt-5"><v-card-text><div class="operateArea"><v-row no-gutters><!-- Operate Btn --><v-col cols="12" sm="3" class="col"><tooltip-btn icon="mdi-plus" :tooltip-text="$t('system.page.add')" @click="method.add()"></tooltip-btn><tooltip-btn icon="mdi-refresh" :tooltip-text="$t('system.page.refresh')" @click="method.refresh()"></tooltip-btn><tooltip-btn icon="mdi-database-import-outline" :tooltip-text="$t('system.page.import')" @click="method.openDialogImport"></tooltip-btn><tooltip-btn icon="mdi-export-variant" :tooltip-text="$t('system.page.export')" @click="method.exportTable"></tooltip-btn></v-col><!-- Search Input --><v-col cols="12" sm="9"><v-row no-gutters @keyup.enter="method.sureSearch"><v-col cols="4"> </v-col><v-col cols="4"> </v-col><v-col cols="4"><v-text-fieldv-model="data.searchForm.goods_owner_name"clearablehide-detailsdensity="comfortable"class="searchInput ml-5 mt-1":label="$t('base.ownerOfCargo.goods_owner_name')"variant="solo"></v-text-field></v-col></v-row></v-col></v-row></div><!-- Table --><divclass="mt-5":style="{height: cardHeight}"><vxe-table ref="xTable" :data="data.tableData" :height="tableHeight" align="center"><template #empty>{{ i18n.global.t('system.page.noData') }}</template><vxe-column type="seq" width="60"></vxe-column><vxe-column field="goods_owner_name" :title="$t('base.ownerOfCargo.goods_owner_name')"></vxe-column><vxe-column field="city" :title="$t('base.ownerOfCargo.city')"></vxe-column><vxe-column field="address" :title="$t('base.ownerOfCargo.address')"></vxe-column><vxe-column field="contact_tel" :title="$t('base.ownerOfCargo.contact_tel')"></vxe-column><vxe-column field="manager" :title="$t('base.ownerOfCargo.manager')"></vxe-column><vxe-column field="creator" :title="$t('base.ownerOfCargo.creator')"></vxe-column><vxe-column field="create_time" :title="$t('base.ownerOfCargo.create_time')"></vxe-column><vxe-column field="operate" :title="$t('system.page.operate')" width="160" :resizable="false" show-overflow><template #default="{ row }"><tooltip-btn:flat="true"icon="mdi-pencil-outline":tooltip-text="$t('system.page.edit')"@click="method.editRow(row)"></tooltip-btn><tooltip-btn:flat="true"icon="mdi-delete-outline":tooltip-text="$t('system.page.delete')":icon-color="errorColor"@click="method.deleteRow(row)"></tooltip-btn></template></vxe-column></vxe-table><custom-pager:current-page="data.tablePage.pageIndex":page-size="data.tablePage.pageSize"perfect:total="data.tablePage.total":page-sizes="PAGE_SIZE":layouts="PAGE_LAYOUT"@page-change="method.handlePageChange"></custom-pager></div></v-card-text></v-card></div><!-- Add or modify data mode window --><addOrUpdateDialog :show-dialog="data.showDialog" :form="data.dialogForm" @close="method.closeDialog" @saveSuccess="method.saveSuccess" /><import-table :show-dialog="data.showDialogImport" @close="method.closeDialogImport" @saveSuccess="method.saveSuccessImport" /></div>
</template><script lang="ts" setup>
import { computed, reactive, onMounted, ref, watch } from 'vue'
import { VxePagerEvents } from 'vxe-table'
import { computedCardHeight, computedTableHeight, errorColor } from '@/constant/style'
import tooltipBtn from '@/components/tooltip-btn.vue'
import { OwnerOfCargoVO, DataProps } from '@/types/Base/OwnerOfCargo'
import { getOwnerOfCargoByPage, deleteOwnerOfCargo } from '@/api/base/ownerOfCargo'
import { hookComponent } from '@/components/system'
import addOrUpdateDialog from './add-or-update-owner-of-cargo.vue'
import i18n from '@/languages/i18n'
import importTable from './import-table.vue'
import { setSearchObject } from '@/utils/common'
import customPager from '@/components/custom-pager.vue'
import { PAGE_SIZE, PAGE_LAYOUT, DEFAULT_PAGE_SIZE } from '@/constant/vxeTable'
import { exportData } from '@/utils/exportTable'
import { DEBOUNCE_TIME } from '@/constant/system'const xTable = ref()const data: DataProps = reactive({searchForm: {goods_owner_name: ''},showDialogImport: false,tableData: [],// Dialog infoshowDialog: false,dialogForm: {id: 0,goods_owner_name: '',city: '',address: '',contact_tel: '',manager: ''},tablePage: {total: 0,pageIndex: 1,pageSize: DEFAULT_PAGE_SIZE},timer: null
})const method = reactive({// When change paginghandlePageChange: ref<VxePagerEvents.PageChange>(({ currentPage, pageSize }) => {data.tablePage.pageIndex = currentPagedata.tablePage.pageSize = pageSizemethod.refresh()}),// Import DialogopenDialogImport: () => {data.showDialogImport = true},closeDialogImport: () => {data.showDialogImport = false},saveSuccessImport: () => {method.refresh()method.closeDialogImport()},sureSearch: () => {data.tablePage.searchObjects = setSearchObject(data.searchForm)method.getOwnerOfCargoList()},// Find Data by PaginationgetOwnerOfCargoList: async () => {const { data: res } = await getOwnerOfCargoByPage(data.tablePage)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}data.tableData = res.data.rowsdata.tablePage.total = res.data.totals},// Add useradd: () => {data.dialogForm = {id: 0,goods_owner_name: '',city: '',address: '',contact_tel: '',manager: ''}data.showDialog = true},// Shut add or update dialogcloseDialog: () => {data.showDialog = false},// after Add or update success.saveSuccess: () => {method.refresh()method.closeDialog()},// Refresh datarefresh: () => {method.getOwnerOfCargoList()},editRow(row: OwnerOfCargoVO) {data.dialogForm = JSON.parse(JSON.stringify(row))data.showDialog = true},deleteRow(row: OwnerOfCargoVO) {hookComponent.$dialog({content: i18n.global.t('system.tips.beforeDeleteMessage'),handleConfirm: async () => {if (row.id) {const { data: res } = await deleteOwnerOfCargo(row.id)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.delete') }${ i18n.global.t('system.tips.success') }`})method.refresh()}}})},// Export tableexportTable: () => {const $table = xTable.valueexportData({table: $table,filename: i18n.global.t('router.sideBar.ownerOfCargo'),columnFilterMethod({ column }: any) {return !['checkbox'].includes(column?.type) && !['operate'].includes(column?.field)}})}
})onMounted(async () => {await method.getOwnerOfCargoList()
})const cardHeight = computed(() => computedCardHeight({ hasTab: false }))const tableHeight = computed(() => computedTableHeight({ hasTab: false }))watch(() => data.searchForm,() => {// debounceif (data.timer) {clearTimeout(data.timer)}data.timer = setTimeout(() => {data.timer = nullmethod.sureSearch()}, DEBOUNCE_TIME)},{deep: true}
)
</script><style scoped lang="less">
.operateArea {width: 100%;min-width: 760px;display: flex;align-items: center;border-radius: 10px;padding: 0 10px;
}.col {display: flex;align-items: center;
}
</style>

在这里插入图片描述

2、窗体代码

<template><v-dialog v-model="isShow" :width="'30%'" transition="dialog-top-transition" :persistent="true"><template #default><v-card><v-toolbar color="white" :title="`${$t('router.sideBar.ownerOfCargo')}`"></v-toolbar><v-card-text><v-form ref="formRef"><v-text-fieldv-model="data.form.goods_owner_name":label="$t('base.ownerOfCargo.goods_owner_name')":rules="data.rules.goods_owner_name"variant="outlined"></v-text-field><v-text-field v-model="data.form.city" :label="$t('base.ownerOfCargo.city')" :rules="data.rules.city" variant="outlined"></v-text-field><v-text-fieldv-model="data.form.address":label="$t('base.ownerOfCargo.address')":rules="data.rules.address"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.manager":label="$t('base.ownerOfCargo.manager')":rules="data.rules.manager"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.contact_tel":label="$t('base.ownerOfCargo.contact_tel')":rules="data.rules.contact_tel"variant="outlined"></v-text-field></v-form></v-card-text><v-card-actions class="justify-end"><v-btn variant="text" @click="method.closeDialog">{{ $t('system.page.close') }}</v-btn><v-btn color="primary" variant="text" @click="method.submit">{{ $t('system.page.submit') }}</v-btn></v-card-actions></v-card></template></v-dialog>
</template><script lang="ts" setup>
import { reactive, computed, ref, watch } from 'vue'
import { OwnerOfCargoVO } from '@/types/Base/OwnerOfCargo'
import i18n from '@/languages/i18n'
import { hookComponent } from '@/components/system/index'
import { addOwnerOfCargo, updateOwnerOfCargo } from '@/api/base/ownerOfCargo'
import { StringLength } from '@/utils/dataVerification/formRule'const formRef = ref()
const emit = defineEmits(['close', 'saveSuccess'])const props = defineProps<{showDialog: booleanform: OwnerOfCargoVO
}>()const isShow = computed(() => props.showDialog)const dialogTitle = computed(() => {if (props.form.id && props.form.id > 0) {return 'update'}return 'add'
})const data = reactive({form: ref<OwnerOfCargoVO>({id: 0,goods_owner_name: '',city: '',address: '',manager: '',contact_tel: ''}),rules: {goods_owner_name: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.ownerOfCargo.goods_owner_name') }!`,(val: string) => StringLength(val, 0, 256) === '' || StringLength(val, 0, 256)],city: [(val: string) => StringLength(val, 0, 128) === '' || StringLength(val, 0, 128)],address: [(val: string) => StringLength(val, 0, 256) === '' || StringLength(val, 0, 256)],manager: [(val: string) => StringLength(val, 0, 64) === '' || StringLength(val, 0, 64)],contact_tel: [(val: string) => StringLength(val, 0, 64) === '' || StringLength(val, 0, 64)]}
})const method = reactive({closeDialog: () => {emit('close')},submit: async () => {const { valid } = await formRef.value.validate()if (valid) {const { data: res } = dialogTitle.value === 'add' ? await addOwnerOfCargo(data.form) : await updateOwnerOfCargo(data.form)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.submit') }${ i18n.global.t('system.tips.success') }`})emit('saveSuccess')} else {hookComponent.$message({type: 'error',content: i18n.global.t('system.checkText.checkFormFail')})}}
})watch(() => isShow.value,(val) => {if (val) {data.form = props.form}}
)
</script><style scoped lang="less">
.v-form {div {margin-bottom: 7px;}
}
</style>

在这里插入图片描述

1.2 接口代码

[Route("goodsowner")]
[ApiController]
[ApiExplorerSettings(GroupName = "Base")]
public class GoodsownerController : BaseController
{#region Args/// <summary>/// goodsowner Service/// </summary>private readonly IGoodsownerService _goodsownerService;/// <summary>/// Localizer Service/// </summary>private readonly IStringLocalizer<ModernWMS.Core.MultiLanguage> _stringLocalizer;#endregion#region constructor/// <summary>/// constructor/// </summary>/// <param name="goodsownerService">goodsowner Service</param>/// <param name="stringLocalizer">Localizer</param>public GoodsownerController(IGoodsownerService goodsownerService, IStringLocalizer<ModernWMS.Core.MultiLanguage> stringLocalizer){this._goodsownerService = goodsownerService;this._stringLocalizer = stringLocalizer;}#endregion#region Api/// <summary>/// page search/// </summary>/// <param name="pageSearch">args</param>/// <returns></returns>[HttpPost("list")]public async Task<ResultModel<PageData<GoodsownerViewModel>>> PageAsync(PageSearch pageSearch){var (data, totals) = await _goodsownerService.PageAsync(pageSearch, CurrentUser);return ResultModel<PageData<GoodsownerViewModel>>.Success(new PageData<GoodsownerViewModel>{Rows = data,Totals = totals});}/// <summary>/// Get all records/// </summary>/// <returns>args</returns>[HttpGet("all")]public async Task<ResultModel<List<GoodsownerViewModel>>> GetAllAsync(){var data = await _goodsownerService.GetAllAsync(CurrentUser);if (data.Any()){return ResultModel<List<GoodsownerViewModel>>.Success(data);}else{return ResultModel<List<GoodsownerViewModel>>.Success(new List<GoodsownerViewModel>());}}/// <summary>/// get a record by id/// </summary>/// <returns>args</returns>[HttpGet]public async Task<ResultModel<GoodsownerViewModel>> GetAsync(int id){var data = await _goodsownerService.GetAsync(id);if (data != null && data.id > 0){return ResultModel<GoodsownerViewModel>.Success(data);}else{return ResultModel<GoodsownerViewModel>.Error(_stringLocalizer["not_exists_entity"]);}}/// <summary>/// add a new record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPost]public async Task<ResultModel<int>> AddAsync(GoodsownerViewModel viewModel){var (id, msg) = await _goodsownerService.AddAsync(viewModel, CurrentUser);if (id > 0){return ResultModel<int>.Success(id);}else{return ResultModel<int>.Error(msg);}}/// <summary>/// update a record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPut]public async Task<ResultModel<bool>> UpdateAsync(GoodsownerViewModel viewModel){var (flag, msg) = await _goodsownerService.UpdateAsync(viewModel);if (flag){return ResultModel<bool>.Success(flag);}else{return ResultModel<bool>.Error(msg, 400, flag);}}/// <summary>/// delete a record/// </summary>/// <param name="id">id</param>/// <returns></returns>[HttpDelete]public async Task<ResultModel<string>> DeleteAsync(int id){var (flag, msg) = await _goodsownerService.DeleteAsync(id);if (flag){return ResultModel<string>.Success(msg);}else{return ResultModel<string>.Error(msg);}}#endregion#region Import/// <summary>/// import goodsowners by excel/// </summary>/// <param name="input">excel data</param>/// <returns></returns>[HttpPost("excel")]public async Task<ResultModel<List<GoodsownerImportViewModel>>> ExcelAsync(List<GoodsownerImportViewModel> input){var (flag, errorData) = await _goodsownerService.ExcelAsync(input, CurrentUser);if (flag){return ResultModel<List<GoodsownerImportViewModel>>.Success(errorData);}else{return ResultModel<List<GoodsownerImportViewModel>>.Error("", 400, errorData);}}#endregion
}

在这里插入图片描述

2.运费设置

在这里插入图片描述

2.1 页面代码

1、主页面代码

<!-- Freight Setting -->
<template><div class="container"><div><!-- Main Content --><v-card class="mt-5"><v-card-text><v-window v-model="data.activeTab"><v-window-item><div class="operateArea"><v-row no-gutters><!-- Operate Btn --><v-col cols="3" class="col"><tooltip-btn icon="mdi-plus" :tooltip-text="$t('system.page.add')" @click="method.add"></tooltip-btn><tooltip-btn icon="mdi-refresh" :tooltip-text="$t('system.page.refresh')" @click="method.refresh"></tooltip-btn><tooltip-btn icon="mdi-database-import-outline" :tooltip-text="$t('system.page.import')" @click="method.openDialogImport"></tooltip-btn><tooltip-btn icon="mdi-export-variant" :tooltip-text="$t('system.page.export')" @click="method.exportTable"> </tooltip-btn></v-col><!-- Search Input --><v-col cols="9"><v-row no-gutters @keyup.enter="method.sureSearch"><v-col cols="4"><v-text-fieldv-model="data.searchForm.carrier"clearablehide-detailsdensity="comfortable"class="searchInput ml-5 mt-1":label="$t('base.freightSetting.carrier')"variant="solo"></v-text-field></v-col><v-col cols="4"><v-text-fieldv-model="data.searchForm.departure_city"clearablehide-detailsdensity="comfortable"class="searchInput ml-5 mt-1":label="$t('base.freightSetting.departure_city')"variant="solo"></v-text-field></v-col><v-col cols="4"><v-text-fieldv-model="data.searchForm.arrival_city"clearablehide-detailsdensity="comfortable"class="searchInput ml-5 mt-1":label="$t('base.freightSetting.arrival_city')"variant="solo"></v-text-field></v-col></v-row></v-col></v-row></div><!-- Table --><divclass="mt-5":style="{height: cardHeight}"><vxe-table ref="xTable" :column-config="{ minWidth: '100px' }" :data="data.tableData" :height="tableHeight" align="center"><template #empty>{{ i18n.global.t('system.page.noData') }}</template><vxe-column type="seq" width="60"></vxe-column><vxe-column type="checkbox" width="50"></vxe-column><vxe-column field="carrier" :title="$t('base.freightSetting.carrier')"></vxe-column><vxe-column field="departure_city" :title="$t('base.freightSetting.departure_city')"></vxe-column><vxe-column field="arrival_city" :title="$t('base.freightSetting.arrival_city')"></vxe-column><vxe-column field="price_per_weight" :title="$t('base.freightSetting.price_per_weight')"></vxe-column><vxe-column field="price_per_volume" :title="$t('base.freightSetting.price_per_volume')"></vxe-column><vxe-column field="min_payment" :title="$t('base.freightSetting.min_payment')"></vxe-column><vxe-column field="creator" :title="$t('base.freightSetting.creator')"></vxe-column><vxe-column field="create_time" width="170px" :title="$t('base.freightSetting.create_time')"></vxe-column><vxe-column field="is_valid" :title="$t('base.freightSetting.is_valid')"><template #default="{ row, column }"><span>{{ row[column.property] ? $t('system.combobox.yesOrNo.yes') : $t('system.combobox.yesOrNo.no') }}</span></template></vxe-column><vxe-column field="operate" :title="$t('system.page.operate')" width="160" :resizable="false" show-overflow><template #default="{ row }"><tooltip-btn:flat="true"icon="mdi-pencil-outline":tooltip-text="$t('system.page.edit')"@click="method.editRow(row)"></tooltip-btn><tooltip-btn:flat="true"icon="mdi-delete-outline":tooltip-text="$t('system.page.delete')":icon-color="errorColor"@click="method.deleteRow(row)"></tooltip-btn></template></vxe-column></vxe-table><custom-pager:current-page="data.tablePage.pageIndex":page-size="data.tablePage.pageSize"perfect:total="data.tablePage.total":page-sizes="PAGE_SIZE":layouts="PAGE_LAYOUT"@page-change="method.handlePageChange"></custom-pager></div></v-window-item></v-window></v-card-text></v-card><addOrUpdateDialog :show-dialog="data.showDialog" :form="data.dialogForm" @close="method.closeDialog" @saveSuccess="method.saveSuccess" /><import-table :show-dialog="data.showDialogImport" @close="method.closeDialogImport" @saveSuccess="method.saveSuccessImport" /></div></div>
</template><script lang="ts" setup>
import { computed, ref, reactive, onMounted, watch } from 'vue'
import { VxePagerEvents } from 'vxe-table'
import { computedCardHeight, computedTableHeight, errorColor } from '@/constant/style'
import { FreightVO } from '@/types/Base/Freight'
import { PAGE_SIZE, PAGE_LAYOUT, DEFAULT_PAGE_SIZE } from '@/constant/vxeTable'
import { hookComponent } from '@/components/system'
import { deleteFreight, getFreightList } from '@/api/base/freightSetting'
import { DEBOUNCE_TIME } from '@/constant/system'
import { setSearchObject } from '@/utils/common'
import { SearchObject } from '@/types/System/Form'
import tooltipBtn from '@/components/tooltip-btn.vue'
import customPager from '@/components/custom-pager.vue'
import addOrUpdateDialog from './add-or-update-freight.vue'
import importTable from './import-table.vue'
import i18n from '@/languages/i18n'
import { exportData } from '@/utils/exportTable'const xTable = ref()const data = reactive({showDialog: false,showDialogImport: false,dialogForm: {id: 0,carrier: '',departure_city: '',arrival_city: '',price_per_weight: 0,price_per_volume: 0,min_payment: 0,is_valid: true},searchForm: {carrier: '',departure_city: '',arrival_city: ''},activeTab: null,tableData: ref<FreightVO[]>([]),tablePage: reactive({total: 0,pageIndex: 1,pageSize: DEFAULT_PAGE_SIZE,searchObjects: ref<Array<SearchObject>>([])}),timer: ref<any>(null)
})const method = reactive({// Open a dialog to addadd: () => {data.dialogForm = {id: 0,carrier: '',departure_city: '',arrival_city: '',price_per_weight: 0,price_per_volume: 0,min_payment: 0,is_valid: true}data.showDialog = true},// Shut add or update dialogcloseDialog: () => {data.showDialog = false},// After add or update success.saveSuccess: () => {method.refresh()method.closeDialog()},// Import DialogopenDialogImport: () => {data.showDialogImport = true},closeDialogImport: () => {data.showDialogImport = false},saveSuccessImport: () => {method.refresh()method.closeDialogImport()},// Refresh datarefresh: () => {method.getFreightList()},getFreightList: async () => {const { data: res } = await getFreightList(data.tablePage)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}data.tableData = res.data.rowsdata.tablePage.total = res.data.totals},editRow(row: FreightVO) {data.dialogForm = JSON.parse(JSON.stringify(row))data.showDialog = true},deleteRow(row: FreightVO) {hookComponent.$dialog({content: i18n.global.t('system.tips.beforeDeleteMessage'),handleConfirm: async () => {if (row.id) {const { data: res } = await deleteFreight(row.id)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.delete') }${ i18n.global.t('system.tips.success') }`})method.refresh()}}})},handlePageChange: ref<VxePagerEvents.PageChange>(({ currentPage, pageSize }) => {data.tablePage.pageIndex = currentPagedata.tablePage.pageSize = pageSizemethod.getFreightList()}),exportTable: () => {const $table = xTable.valueexportData({table: $table,filename: i18n.global.t('router.sideBar.freightSetting'),columnFilterMethod({ column }: any) {return !['checkbox'].includes(column?.type) && !['operate'].includes(column?.field)}})},importTable: () => {const $table = xTable.value$table.importData()},sureSearch: () => {data.tablePage.searchObjects = setSearchObject(data.searchForm)method.getFreightList()}
})onMounted(() => {method.getFreightList()
})const cardHeight = computed(() => computedCardHeight({ hasTab: false }))
const tableHeight = computed(() => computedTableHeight({ hasTab: false }))watch(() => data.searchForm,() => {// debounceif (data.timer) {clearTimeout(data.timer)}data.timer = setTimeout(() => {data.timer = nullmethod.sureSearch()}, DEBOUNCE_TIME)},{deep: true}
)
</script><style scoped lang="less">
.operateArea {width: 100%;min-width: 760px;display: flex;align-items: center;border-radius: 10px;padding: 0 10px;
}.col {display: flex;align-items: center;
}
</style>

在这里插入图片描述

2、窗体代码

<!-- Freight Setting Operate Dialog -->
<template><v-dialog v-model="isShow" :width="'30%'" transition="dialog-top-transition" :persistent="true"><template #default><v-card><v-toolbar color="white" :title="`${$t('router.sideBar.freightSetting')}`"></v-toolbar><v-card-text><v-form ref="formRef"><v-text-fieldv-model="data.form.carrier":label="$t('base.freightSetting.carrier')":rules="data.rules.carrier"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.departure_city":label="$t('base.freightSetting.departure_city')":rules="data.rules.departure_city"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.arrival_city":label="$t('base.freightSetting.arrival_city')":rules="data.rules.arrival_city"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.price_per_weight":label="$t('base.freightSetting.price_per_weight')":rules="data.rules.price_per_weight"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.price_per_volume":label="$t('base.freightSetting.price_per_volume')":rules="data.rules.price_per_volume"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.min_payment":label="$t('base.freightSetting.min_payment')":rules="data.rules.min_payment"variant="outlined"></v-text-field><v-switchv-model="data.form.is_valid"color="primary":label="$t('base.freightSetting.is_valid')":rules="data.rules.is_valid"></v-switch></v-form></v-card-text><v-card-actions class="justify-end"><v-btn variant="text" @click="method.closeDialog">{{ $t('system.page.close') }}</v-btn><v-btn color="primary" variant="text" @click="method.submit">{{ $t('system.page.submit') }}</v-btn></v-card-actions></v-card></template></v-dialog>
</template><script lang="ts" setup>
import { reactive, computed, ref, watch } from 'vue'
import i18n from '@/languages/i18n'
import { hookComponent } from '@/components/system/index'
import { addFreight, updateFreight } from '@/api/base/freightSetting'
import { FreightVO } from '@/types/Base/Freight'
import { StringLength, IsDecimal } from '@/utils/dataVerification/formRule'const formRef = ref()
const emit = defineEmits(['close', 'saveSuccess'])const props = defineProps<{showDialog: booleanform: FreightVO
}>()const isShow = computed(() => props.showDialog)const dialogTitle = computed(() => {if (props.form.id && props.form.id > 0) {return 'update'}return 'add'
})const data = reactive({form: ref<FreightVO>({id: 0,carrier: '',departure_city: '',arrival_city: '',price_per_weight: 0,price_per_volume: 0,min_payment: 0,is_valid: true}),rules: {carrier: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.carrier') }!`,(val: string) => StringLength(val, 0, 256) === '' || StringLength(val, 0, 256)],departure_city: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.departure_city') }!`,(val: string) => StringLength(val, 0, 128) === '' || StringLength(val, 0, 128)],arrival_city: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.arrival_city') }!`,(val: string) => StringLength(val, 0, 128) === '' || StringLength(val, 0, 128)],price_per_weight: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.price_per_weight') }!`,(val: number) => IsDecimal(val, 'nonNegative', 6, 2) === '' || IsDecimal(val, 'nonNegative', 6, 2)],price_per_volume: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.price_per_volume') }!`,(val: number) => IsDecimal(val, 'nonNegative', 6, 2) === '' || IsDecimal(val, 'nonNegative', 6, 2)],min_payment: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.freightSetting.min_payment') }!`,(val: number) => IsDecimal(val, 'nonNegative', 8, 2) === '' || IsDecimal(val, 'nonNegative', 8, 2)],is_valid: []}
})const method = reactive({closeDialog: () => {emit('close')},initForm: () => {data.form = props.form},submit: async () => {const { valid } = await formRef.value.validate()if (valid) {const { data: res } = dialogTitle.value === 'add' ? await addFreight(data.form) : await updateFreight(data.form)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.submit') }${ i18n.global.t('system.tips.success') }`})emit('saveSuccess')} else {hookComponent.$message({type: 'error',content: i18n.global.t('system.checkText.checkFormFail')})}}
})watch(() => isShow.value,(val) => {if (val) {method.initForm()}}
)
</script><style scoped lang="less">
.v-form {div {margin-bottom: 7px;}
}
</style>

在这里插入图片描述

2.2 接口代码

     [Route("freightfee")][ApiController][ApiExplorerSettings(GroupName = "Base")]public class FreightfeeController : BaseController{#region Args/// <summary>/// freightfee Service/// </summary>private readonly IFreightfeeService _freightfeeService;/// <summary>/// Localizer Service/// </summary>private readonly IStringLocalizer<ModernWMS.Core.MultiLanguage> _stringLocalizer;#endregion#region constructor/// <summary>/// constructor/// </summary>/// <param name="freightfeeService">freightfee Service</param>/// <param name="stringLocalizer">Localizer</param>public FreightfeeController(IFreightfeeService freightfeeService, IStringLocalizer<ModernWMS.Core.MultiLanguage> stringLocalizer){this._freightfeeService = freightfeeService;this._stringLocalizer= stringLocalizer;}#endregion#region Api/// <summary>/// page search/// </summary>/// <param name="pageSearch">args</param>/// <returns></returns>[HttpPost("list")]public async Task<ResultModel<PageData<FreightfeeViewModel>>> PageAsync(PageSearch pageSearch){var (data, totals) = await _freightfeeService.PageAsync(pageSearch, CurrentUser);return ResultModel<PageData<FreightfeeViewModel>>.Success(new PageData<FreightfeeViewModel>{Rows = data,Totals = totals});}/// <summary>/// get all records/// </summary>/// <returns>args</returns>[HttpGet("all")]public async Task<ResultModel<List<FreightfeeViewModel>>> GetAllAsync(){var data = await _freightfeeService.GetAllAsync(CurrentUser);if (data.Any()){return ResultModel<List<FreightfeeViewModel>>.Success(data);}else{return ResultModel<List<FreightfeeViewModel>>.Success(new List<FreightfeeViewModel>());}}/// <summary>/// get a record by id/// </summary>/// <returns>args</returns>[HttpGet]public async Task<ResultModel<FreightfeeViewModel>> GetAsync(int id){var data = await _freightfeeService.GetAsync(id);if (data!=null){return ResultModel<FreightfeeViewModel>.Success(data);}else{return ResultModel<FreightfeeViewModel>.Error(_stringLocalizer["not_exists_entity"]);}}/// <summary>/// add a new record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPost]public async Task<ResultModel<int>> AddAsync(FreightfeeViewModel viewModel){var (id, msg) = await _freightfeeService.AddAsync(viewModel,CurrentUser);if (id > 0){return ResultModel<int>.Success(id);}else{return ResultModel<int>.Error(msg);}}/// <summary>/// update a record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPut]public async Task<ResultModel<bool>> UpdateAsync(FreightfeeViewModel viewModel){var (flag, msg) = await _freightfeeService.UpdateAsync(viewModel);if (flag){return ResultModel<bool>.Success(flag);}else{return ResultModel<bool>.Error(msg, 400, flag);}}/// <summary>/// delete a record/// </summary>/// <param name="id">id</param>/// <returns></returns>[HttpDelete]public async Task<ResultModel<string>> DeleteAsync(int id){var (flag, msg) = await _freightfeeService.DeleteAsync(id);if (flag){return ResultModel<string>.Success(msg);}else{return ResultModel<string>.Error(msg);}}/// <summary>/// import freight fee by excel/// </summary>/// <param name="excel_datas">excel datas</param>/// <returns></returns>[HttpPost("excel")]public async Task<ResultModel<string>> ExcelAsync(List<FreightfeeExcelmportViewModel> excel_datas){var (flag, msg) = await _freightfeeService.ExcelAsync(excel_datas, CurrentUser);if (flag){return ResultModel<string>.Success(msg);}else{return ResultModel<string>.Error(msg);}}#endregion}

在这里插入图片描述

3.客户信息

在这里插入图片描述

3.1 页面代码

1、主页面代码

<!-- customer Setting -->
<template><div class="container"><div><!-- Main Content --><v-card class="mt-5"><v-card-text><!-- <v-window v-model="data.activeTab"><v-window-item> --><div class="operateArea"><v-row no-gutters><!-- Operate Btn --><v-col cols="12" sm="3" class="col"><tooltip-btn icon="mdi-plus" :tooltip-text="$t('system.page.add')" @click="method.add()"></tooltip-btn><tooltip-btn icon="mdi-refresh" :tooltip-text="$t('system.page.refresh')" @click="method.refresh()"></tooltip-btn><tooltip-btn icon="mdi-database-import-outline" :tooltip-text="$t('system.page.import')" @click="method.openDialogImport"></tooltip-btn><tooltip-btn icon="mdi-export-variant" :tooltip-text="$t('system.page.export')" @click="method.exportTable"> </tooltip-btn></v-col><!-- Search Input --><v-col cols="12" sm="9"><v-row no-gutters @keyup.enter="method.sureSearch"><v-col cols="12" sm="4"></v-col><v-col cols="12" sm="4"></v-col><v-col cols="12" sm="4"><v-text-fieldv-model="data.searchForm.customer_name"clearablehide-detailsdensity="comfortable"class="searchInput ml-5 mt-1":label="$t('base.customer.customer_name')"variant="solo"></v-text-field></v-col></v-row></v-col></v-row></div><!-- Table --><divclass="mt-5":style="{height: cardHeight}"><vxe-table ref="xTable" :data="data.tableData" :height="tableHeight" align="center"><template #empty>{{ i18n.global.t('system.page.noData') }}</template><vxe-column type="seq" width="60"></vxe-column><vxe-column type="checkbox" width="50"></vxe-column><vxe-column field="customer_name" :title="$t('base.customer.customer_name')"></vxe-column><vxe-column field="city" :title="$t('base.customer.city')"></vxe-column><vxe-column field="address" :title="$t('base.customer.address')"></vxe-column><vxe-column field="manager" :title="$t('base.customer.manager')"></vxe-column><vxe-column field="email" :title="$t('base.customer.email')"></vxe-column><vxe-column field="contact_tel" :title="$t('base.customer.contact_tel')"></vxe-column><vxe-column field="creator" :title="$t('base.customer.creator')"></vxe-column><vxe-column field="create_time" :title="$t('base.customer.create_time')"><!-- :formatter="['formatDate', 'yyyy-MM-dd HH:mm:ss']" --><template #default="{ row, column }"><span>{{ formatDate(row[column.property]) }}</span></template></vxe-column><vxe-column field="last_update_time" :title="$t('base.customer.last_update_time')"><template #default="{ row, column }"><span>{{ formatDate(row[column.property]) }}</span></template></vxe-column><vxe-column field="operate" :title="$t('system.page.operate')" width="160" :resizable="false" show-overflow><template #default="{ row }"><tooltip-btn:flat="true"icon="mdi-pencil-outline":tooltip-text="$t('system.page.edit')"@click="method.editRow(row)"></tooltip-btn><tooltip-btn:flat="true"icon="mdi-delete-outline":tooltip-text="$t('system.page.delete')":icon-color="errorColor"@click="method.deleteRow(row)"></tooltip-btn></template></vxe-column></vxe-table><custom-pager:current-page="data.tablePage.pageIndex":page-size="data.tablePage.pageSize"perfect:total="data.tablePage.total":page-sizes="PAGE_SIZE":layouts="PAGE_LAYOUT"@page-change="method.handlePageChange"></custom-pager></div><!-- </v-window-item></v-window> --></v-card-text></v-card></div></div><addOrUpdateDialog :show-dialog="data.showDialog" :form="data.dialogForm" @close="method.closeDialog" @saveSuccess="method.saveSuccess" /><importCustomerTable :show-dialog="data.showDialogImport" @close="method.closeDialogImport" @saveSuccess="method.saveSuccessImport" />
</template><script lang="tsx" setup>
import { computed, ref, reactive, onMounted, watch } from 'vue'
import { VxePagerEvents } from 'vxe-table'
import { computedCardHeight, computedTableHeight, errorColor } from '@/constant/style'
import { CustomerVO, DataProps } from '@/types/Base/Customer'
import { PAGE_SIZE, PAGE_LAYOUT, DEFAULT_PAGE_SIZE } from '@/constant/vxeTable'
import tooltipBtn from '@/components/tooltip-btn.vue'
import addOrUpdateDialog from './add-or-update-customer.vue'
import { hookComponent } from '@/components/system'
import { DEBOUNCE_TIME } from '@/constant/system'
import { setSearchObject } from '@/utils/common'
import { SearchObject } from '@/types/System/Form'
import i18n from '@/languages/i18n'
import { getCustomerList, deleteCustomer } from '@/api/base/customer'
import importCustomerTable from './import-customer-table.vue'
import { formatDate } from '@/utils/format/formatSystem'
import customPager from '@/components/custom-pager.vue'
import { exportData } from '@/utils/exportTable'const xTable = ref()const data = reactive({searchForm: {customer_name: ''},tableData: [],// activeTab: null,showDialog: false,showDialogImport: false,dialogForm: {id: 0,customer_name: '',city: '',address: '',manager: '',email: '',contact_tel: '',is_valid: true},tablePage: {total: 0,pageIndex: 1,pageSize: DEFAULT_PAGE_SIZE,searchObjects: ref<Array<SearchObject>>([])},timer: ref<any>(null)
})const method = reactive({// Import DialogopenDialogImport: () => {data.showDialogImport = true},closeDialogImport: () => {data.showDialogImport = false},saveSuccessImport: () => {method.refresh()method.closeDialog()},sureSearch: () => {data.tablePage.searchObjects = setSearchObject(data.searchForm)method.getData()},// Add useradd: () => {data.dialogForm = {id: 0,customer_name: '',city: '',address: '',manager: '',email: '',contact_tel: '',is_valid: true}data.showDialog = true},// Shut add or update dialogcloseDialog: () => {data.showDialog = false},// after Add or update success.saveSuccess: () => {method.refresh()method.closeDialog()},// Refresh datarefresh: () => {method.getData()},editRow(row: CustomerVO) {data.dialogForm = JSON.parse(JSON.stringify(row))data.showDialog = true},deleteRow(row: CustomerVO) {hookComponent.$dialog({content: i18n.global.t('system.tips.beforeDeleteMessage'),handleConfirm: async () => {if (row.id) {const { data: res } = await deleteCustomer(row.id)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.delete') }${ i18n.global.t('system.tips.success') }`})method.refresh()}}})},handlePageChange: ref<VxePagerEvents.PageChange>(({ currentPage, pageSize }) => {data.tablePage.pageIndex = currentPagedata.tablePage.pageSize = pageSizemethod.getData()}),exportTable: () => {const $table = xTable.valueexportData({table: $table,filename: i18n.global.t('router.sideBar.customer'),columnFilterMethod({ column }: any) {return !['checkbox'].includes(column?.type) && !['operate'].includes(column?.field)}})},getData: async () => {const { data: res } = await getCustomerList(data.tablePage)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}data.tableData = res.data.rowsdata.tablePage.total = res.data.totals}
})
onMounted(() => {method.getData()
})const cardHeight = computed(() => computedCardHeight({ hasTab: false }))
const tableHeight = computed(() => computedTableHeight({ hasTab: false }))watch(() => data.searchForm,() => {// debounceif (data.timer) {clearTimeout(data.timer)}data.timer = setTimeout(() => {data.timer = nullmethod.sureSearch()}, DEBOUNCE_TIME)},{deep: true}
)
</script><style scoped lang="less">
.operateArea {width: 100%;min-width: 760px;display: flex;align-items: center;border-radius: 10px;padding: 0 10px;
}.col {display: flex;align-items: center;
}
</style>

在这里插入图片描述

2、窗体代码

<template><v-dialog v-model="isShow" :width="'30%'" transition="dialog-top-transition" :persistent="true"><template #default><v-card><v-toolbar color="white" :title="`${$t('router.sideBar.customer')}`"></v-toolbar><v-card-text><v-form ref="formRef"><v-text-fieldv-model="data.form.customer_name":label="$t('base.customer.customer_name')":rules="data.rules.customer_name"variant="outlined"></v-text-field><v-text-field v-model="data.form.city" :label="$t('base.customer.city')" :rules="data.rules.city" variant="outlined"></v-text-field><v-text-fieldv-model="data.form.email":label="$t('base.customer.email')":rules="data.rules.email"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.address":label="$t('base.customer.address')":rules="data.rules.address"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.manager":label="$t('base.customer.manager')":rules="data.rules.manager"variant="outlined"></v-text-field><v-text-fieldv-model="data.form.contact_tel":label="$t('base.customer.contact_tel')":rules="data.rules.contact_tel"variant="outlined"></v-text-field></v-form></v-card-text><v-card-actions class="justify-end"><v-btn variant="text" @click="method.closeDialog">{{ $t('system.page.close') }}</v-btn><v-btn color="primary" variant="text" @click="method.submit">{{ $t('system.page.submit') }}</v-btn></v-card-actions></v-card></template></v-dialog>
</template><script lang="ts" setup>
import { reactive, computed, ref, watch } from 'vue'
import { CustomerVO } from '@/types/Base/Customer'
import i18n from '@/languages/i18n'
import { hookComponent } from '@/components/system/index'
import { addCustomer, updateCustomer } from '@/api/base/customer'const formRef = ref()
const emit = defineEmits(['close', 'saveSuccess'])const props = defineProps<{showDialog: booleanform: CustomerVO
}>()const isShow = computed(() => props.showDialog)const dialogTitle = computed(() => {if (props.form.id && props.form.id > 0) {return 'update'}return 'add'
})const data = reactive({form: ref<CustomerVO>({id: 0,customer_name: '',city: '',address: '',manager: '',email: '',contact_tel: '',is_valid: true}),rules: {customer_name: [(val: string) => !!val || `${ i18n.global.t('system.checkText.mustInput') }${ i18n.global.t('base.customer.customer_name') }!`],city: [],address: [],manager: [],email: [],contact_tel: [],is_valid: []}
})const method = reactive({closeDialog: () => {emit('close')},submit: async () => {const { valid } = await formRef.value.validate()if (valid) {const { data: res } = dialogTitle.value === 'add' ? await addCustomer(data.form) : await updateCustomer(data.form)if (!res.isSuccess) {hookComponent.$message({type: 'error',content: res.errorMessage})return}hookComponent.$message({type: 'success',content: `${ i18n.global.t('system.page.submit') }${ i18n.global.t('system.tips.success') }`})emit('saveSuccess')} else {hookComponent.$message({type: 'error',content: i18n.global.t('system.checkText.checkFormFail')})}}
})watch(() => isShow.value,(val) => {if (val) {data.form = props.form}}
)
</script><style scoped lang="less">
.v-form {div {margin-bottom: 7px;}
}
</style>

在这里插入图片描述

3.2 接口代码

    [Route("customer")][ApiController][ApiExplorerSettings(GroupName = "Base")]public class CustomerController : BaseController{#region Args/// <summary>/// customer Service/// </summary>private readonly ICustomerService _customerService;/// <summary>/// Localizer Service/// </summary>private readonly IStringLocalizer<ModernWMS.Core.MultiLanguage> _stringLocalizer;#endregion#region constructor/// <summary>/// constructor/// </summary>/// <param name="customerService">customer Service</param>/// <param name="stringLocalizer">Localizer</param>public CustomerController(ICustomerService customerService, IStringLocalizer<ModernWMS.Core.MultiLanguage> stringLocalizer){this._customerService = customerService;this._stringLocalizer = stringLocalizer;}#endregion#region Api/// <summary>/// page search/// </summary>/// <param name="pageSearch">args</param>/// <returns></returns>[HttpPost("list")]public async Task<ResultModel<PageData<CustomerViewModel>>> PageAsync(PageSearch pageSearch){var (data, totals) = await _customerService.PageAsync(pageSearch, CurrentUser);return ResultModel<PageData<CustomerViewModel>>.Success(new PageData<CustomerViewModel>{Rows = data,Totals = totals});}/// <summary>/// Get all records/// </summary>/// <returns>args</returns>[HttpGet("all")]public async Task<ResultModel<List<CustomerViewModel>>> GetAllAsync(){var data = await _customerService.GetAllAsync(CurrentUser);if (data.Any()){return ResultModel<List<CustomerViewModel>>.Success(data);}else{return ResultModel<List<CustomerViewModel>>.Success(new List<CustomerViewModel>());}}/// <summary>/// get a record by id/// </summary>/// <returns>args</returns>[HttpGet]public async Task<ResultModel<CustomerViewModel>> GetAsync(int id){var data = await _customerService.GetAsync(id);if (data != null && data.id > 0){return ResultModel<CustomerViewModel>.Success(data);}else{return ResultModel<CustomerViewModel>.Error(_stringLocalizer["not_exists_entity"]);}}/// <summary>/// add a new record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPost]public async Task<ResultModel<int>> AddAsync(CustomerViewModel viewModel){var (id, msg) = await _customerService.AddAsync(viewModel, CurrentUser);if (id > 0){return ResultModel<int>.Success(id);}else{return ResultModel<int>.Error(msg);}}/// <summary>/// update a record/// </summary>/// <param name="viewModel">args</param>/// <returns></returns>[HttpPut]public async Task<ResultModel<bool>> UpdateAsync(CustomerViewModel viewModel){var (flag, msg) = await _customerService.UpdateAsync(viewModel);if (flag){return ResultModel<bool>.Success(flag);}else{return ResultModel<bool>.Error(msg, 400, flag);}}/// <summary>/// delete a record/// </summary>/// <param name="id">id</param>/// <returns></returns>[HttpDelete]public async Task<ResultModel<string>> DeleteAsync(int id){var (flag, msg) = await _customerService.DeleteAsync(id);if (flag){return ResultModel<string>.Success(msg);}else{return ResultModel<string>.Error(msg);}}#endregion#region Import/// <summary>/// import customers by excel/// </summary>/// <param name="input">excel data</param>/// <returns></returns>[HttpPost("excel")]public async Task<ResultModel<List<CustomerImportViewModel>>> ExcelAsync(List<CustomerImportViewModel> input){var (flag, errorData) = await _customerService.ExcelAsync(input, CurrentUser);if (flag){return ResultModel<List<CustomerImportViewModel>>.Success(errorData);}else{return ResultModel<List<CustomerImportViewModel>>.Error("", 400, errorData);}}#endregion}

在这里插入图片描述


http://www.ppmy.cn/news/570482.html

相关文章

【OpenCV】IPCamera读取网络摄像头实时画面

软硬件平台 VS2015 OpenCV 3.2 IPCamera 沃仕达T7866WIP CGI协议 代码 #include "stdafx.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> #include <iostream>using nam…

运算放大器(一):电压跟随器

一、电压跟随器 电压跟随器&#xff08;单位增益放大器、缓冲放大器或隔离放大器&#xff09;是一种电压放大倍数为 1 的运算放大器&#xff0c;能够将输入信号的电压放大到同样的幅度并输出&#xff0c;同时保持输入输出电阻不变&#xff08;电压跟随器的输入电阻很大&#x…

操作系统——基于信号量机制的并发程序设计

一、实验题目 基于信号量机制的并发程序设计 二、实验目的 (1) 回顾操作系统进程、线程的有关概念&#xff0c;针对经典的同步、互斥、死锁与饥饿问题进行并发 程序设计。 (2) 了解互斥体对象&#xff0c;利用互斥与同步操作编写读者-写者问题的并发程序&#xff0c;加深…

war3改键精灵脱壳去广告

今天偶尔在局域网打了几把dota&#xff0c;发现某改键精灵在每次启动时自动弹出两次广告&#xff0c;全屏游戏自动弹出到桌面。十分捉急&#xff0c;于是有此破文。 OD载入 》脱壳》再载入dump》搜索字符串》 采用我认为最暴力最简单的方法NOP掉&#xff08;顺便把自动升级NOP掉…

Python实现 dota 改建精灵

如题&#xff0c;用Python3实现 dota改建精灵。本质原理是通过改变键盘按键映射关系。比如按下数字键1&#xff0c;映射到字母A。映射关系可以自定义。 这样就构成了改建逻辑。 实现工具清单如下&#xff1a; python 3.7.3python库&#xff1a;PyHook3 &#xff0c;关于该库的…

linux shell 键盘输入 $,linuxshell在while中用read从键盘输入的实现

系统是ubuntu 14.04 64bit&#xff0c;之前曾想安装Stream来玩dota2&#xff0c;但最终没成功。由于Stream只有32bit&#xff0c;安装Stream时也安装了大量32bit的库。删除Stream后&#xff0c;这些库也一直没管&#xff0c;今天忽然心血来潮&#xff0c;想清理一下系统&#x…

hw1-浅谈Dota2设计元素

今年的TI9赛事在中国上海举行&#xff0c;可谓是Dota2玩家们的一大幸事。但是&#xff0c;LGD战队止步于季军&#xff0c;也让我们的粉丝心凉了一截。8月25日&#xff0c;OG战队以3比1战胜Liquid战队&#xff0c;将2019Dota2国际邀请赛冠军收入囊中&#xff0c;实现了在该项赛事…

Dota 2 with Large Scale Deep Reinforcement Learning翻译

摘要 2019年4月13日&#xff0c;OpenAI Five成为第一个在电子竞技游戏中击败世界冠军的AI系统。Dota2游戏为AI系统提供了新的挑战&#xff0c;例如长时间相关的视野&#xff0c;不完全的信息和复杂的连续状态动作空间&#xff0c;所有这些挑战将会要求具有更强能力的AI系统。O…