refactor(erp): 调整客户添加页面样式和功能

- 优化客户添加页面的输入框样式
- 更新仓库选择和区域选择功能
- 修复电话号码验证逻辑
- 调整产品列表和选择组件的显示
- 修改区域选择组件的样式
- 更新私钥文件
This commit is contained in:
郑彪辉
2025-08-11 23:15:01 +08:00
parent 90adee4320
commit b8fbae24fb
6 changed files with 121 additions and 110 deletions

View File

@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View File

@@ -1,15 +1,17 @@
<template> <template>
<view class="bg-[var(--page-bg-color)] min-h-[100vh] overflow-hidden form-edit" :style="themeColor()"> <view class="bg-[var(--page-bg-color)] min-h-[100vh] overflow-hidden form-edit" :style="themeColor()">
<u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef" labelWidth="180rpx"> <u-form labelPosition="left" :model="formData" errorType='toast' :rules="rules" ref="formRef"
labelWidth="180rpx">
<view class="sidebar-margin card-template mt-[var(--top-m)] py-[20rpx]"> <view class="sidebar-margin card-template mt-[var(--top-m)] py-[20rpx]">
<!-- <view> <!-- <view>
<u-form-item :label="t('code')" prop="code" required borderBottom> <u-form-item :label="t('code')" prop="code" required borderBottom>
<u-input fontSize="28rpx" v-model.trim="formData.code" disabled clearable placeholderStyle="color: #888" :placeholder="t('codePlaceholderNew')"/> <u-input fontSize="28rpx" v-model.trim="formData.code" disabled clearable placeholderStyle="color: #888" :placeholder="t('codePlaceholderNew')"/>
</u-form-item> </u-form-item>
</view> --> </view> -->
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('name')" prop="name" required borderBottom> <u-form-item :label="t('name')" prop="name" required borderBottom>
<u-input fontSize="28rpx" v-model.trim="formData.name" clearable placeholderStyle="color: #888" :placeholder="t('namePlaceholder')"/> <u-input fontSize="28rpx" v-model.trim="formData.name" clearable placeholderStyle="color: #888"
:placeholder="t('namePlaceholder')" />
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
@@ -26,17 +28,20 @@
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('contact')" prop="contact" required borderBottom> <u-form-item :label="t('contact')" prop="contact" required borderBottom>
<u-input fontSize="28rpx" v-model="formData.contact" :placeholder="t('contactPlaceholder')" ></u-input> <u-input fontSize="28rpx" v-model="formData.contact"
:placeholder="t('contactPlaceholder')"></u-input>
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('phone')" prop="phone" required borderBottom> <u-form-item :label="t('phone')" prop="phone" required borderBottom>
<u-input fontSize="28rpx" v-model.trim="formData.phone" type="number" maxlength="11" clearable :placeholder="t('phonePlaceholder')" placeholderStyle="color: #888"/> <u-input fontSize="28rpx" v-model.trim="formData.phone" type="number" maxlength="11" clearable
:placeholder="t('phonePlaceholder')" placeholderStyle="color: #888" />
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('telephone')" prop="telephone" borderBottom> <u-form-item :label="t('telephone')" prop="telephone" borderBottom>
<u-input fontSize="28rpx" v-model="formData.telephone" :placeholder="t('telephonePlaceholder')" ></u-input> <u-input fontSize="28rpx" v-model="formData.telephone"
:placeholder="t('telephonePlaceholder')"></u-input>
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
@@ -53,24 +58,28 @@
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('address')" prop="address" borderBottom> <u-form-item :label="t('address')" prop="address" borderBottom>
<u-input fontSize="28rpx" v-model="formData.address" clearable maxlength="120" :placeholder="t('addressPlaceholder')" placeholderStyle="color: #888"/> <u-input fontSize="28rpx" v-model="formData.address" clearable maxlength="120"
:placeholder="t('addressPlaceholder')" placeholderStyle="color: #888" />
</u-form-item> </u-form-item>
</view> </view>
<view class="mt-[16rpx]"> <view class="mt-[16rpx]">
<u-form-item :label="t('description')" prop="description"> <u-form-item :label="t('description')" prop="description">
<u-textarea fontSize="28rpx" v-model="formData.description" :placeholder="t('descriptionPlaceholder')" ></u-textarea> <u-textarea fontSize="28rpx" v-model="formData.description"
:placeholder="t('descriptionPlaceholder')"></u-textarea>
</u-form-item> </u-form-item>
</view> </view>
</view> </view>
</u-form> </u-form>
<view class="w-full footer" v-if="hasPermission('erp_base_customer_add')"> <view class="w-full footer" v-if="hasPermission('erp_base_customer_add')">
<view class="py-[var(--top-m)] px-[var(--sidebar-m)] footer w-full fixed bottom-0 left-0 right-0 box-border"> <view
<button hover-class="none" class="!bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500" class="py-[var(--top-m)] px-[var(--sidebar-m)] footer w-full fixed bottom-0 left-0 right-0 box-border">
@click="handSave" :disabled="loading" :class="{'opacity-50': loading}">{{t('save')}}</button> <button hover-class="none"
class="!bg-[var(--primary-color)] text-[#fff] h-[80rpx] leading-[80rpx] rounded-[100rpx] text-[26rpx] font-500"
@click="handSave" :disabled="loading" :class="{'opacity-50': loading}">{{t('save')}}</button>
</view> </view>
</view> </view>
<area-select ref="areaRef" @complete="areaSelectComplete" :area-id="0"/> <area-select ref="areaRef" @complete="areaSelectComplete" :area-id="0" />
</view> </view>
</template> </template>
@@ -79,19 +88,19 @@
import { ref, reactive, computed } from 'vue' import { ref, reactive, computed } from 'vue'
import { onLoad, onReady, onShow } from '@dcloudio/uni-app'; import { onLoad, onReady, onShow } from '@dcloudio/uni-app';
import { t } from '@/locale' import { t } from '@/locale'
import { addCustomer,getusersList,getWarehouseSelect} from '@/addon/erp/api/base'; import { addCustomer, getusersList, getWarehouseSelect } from '@/addon/erp/api/base';
import { generatedCode } from '@/addon/erp/utils/common'; import { generatedCode } from '@/addon/erp/utils/common';
import { redirect } from '@/utils/common'; import { redirect } from '@/utils/common';
import useMemberStore from '@/stores/member' import useMemberStore from '@/stores/member'
import usePermission from '@/utils/usePermission' import usePermission from '@/utils/usePermission'
const { hasPermission } = usePermission() const { hasPermission } = usePermission()
interface Warehouse { interface Warehouse {
id: number; id : number;
name: string; name : string;
} }
const memberStore = useMemberStore() const memberStore = useMemberStore()
const formRef: any = ref(null) const formRef : any = ref(null)
const loading = ref(false) const loading = ref(false)
const areaRef = ref() const areaRef = ref()
@@ -100,24 +109,24 @@
const warehouseList = ref<Warehouse[]>([]); const warehouseList = ref<Warehouse[]>([]);
const rules = computed(() => { const rules = computed(() => {
return { return {
// 'code': { // 'code': {
// type: 'string', // type: 'string',
// required: true, // required: true,
// message: t('codePlaceholderNew'), // message: t('codePlaceholderNew'),
// trigger: ['blur', 'change'], // trigger: ['blur', 'change'],
// }, // },
'name': { 'name': {
type: 'string', type: 'string',
required: true, required: true,
message: t('namePlaceholder'), message: t('namePlaceholder'),
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, },
'warehouse_id': { 'warehouse_id': {
type: 'number', type: 'number',
required: true, required: true,
message: '请选择仓库', message: '请选择仓库',
trigger: ['change'], trigger: ['change'],
}, },
'contact': { 'contact': {
type: 'string', type: 'string',
@@ -126,24 +135,24 @@
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, },
'phone': [ 'phone': [
{ {
type: 'string', type: 'string',
required: true, required: true,
message: t('phonePlaceholder'), message: t('phonePlaceholder'),
trigger: ['blur', 'change'], trigger: ['blur', 'change'],
}, },
{ {
validator(rule: any, value: any, callback: any) { validator(rule : any, value : any, callback : any) {
let mobile = /^1[3-9]\d{9}$/; let mobile = new RegExp('^1[3-9]\d{9}$');
if (!mobile.test(value)){ if (!mobile.test(value)) {
callback(new Error(t('mobileError'))) callback(new Error(t('mobileError')))
} else { } else {
callback() callback()
} }
} }
} }
] ]
} }
}) })
const formData = reactive({ const formData = reactive({
code: generatedCode("CT"), code: generatedCode("CT"),
@@ -163,27 +172,27 @@
getAllUserList() getAllUserList()
getWarehouseSelectList() getWarehouseSelectList()
}) })
const getWarehouseSelectList= ()=>{ const getWarehouseSelectList = () => {
getWarehouseSelect().then(res =>{ getWarehouseSelect().then(res => {
warehouseList.value=res.data|| [] warehouseList.value = res.data || []
}) })
} }
const warehouseIdChange = (e : any) => { const warehouseIdChange = (e : any) => {
formData.warehouse_id = e?.id ||'' formData.warehouse_id = e?.id || ''
if (formRef.value) { if (formRef.value) {
formRef.value.validateField('warehouse_id'); formRef.value.validateField('warehouse_id');
} }
} }
const selectArea = () => { const selectArea = () => {
isSelectAddress.value = true isSelectAddress.value = true
areaRef.value.open() areaRef.value.open()
} }
const areaSelectComplete = (event: any) => { const areaSelectComplete = (event : any) => {
let cityArr = [] as any[]; let cityArr = [] as any[];
cityArr = [event.province.id || 0, event.city.id || 0, event.district.id || 0]; cityArr = [event.province.id || 0, event.city.id || 0, event.district.id || 0];
formData.city = cityArr.join(','); formData.city = cityArr.join(',');
formData.cityName = `${event.province.name || ''}${event.city.name || ''}${event.district.name || ''}` formData.cityName = `${event.province.name || ''}${event.city.name || ''}${event.district.name || ''}`
isSelectAddress.value = false; isSelectAddress.value = false;
} }
/** /**
@@ -198,7 +207,7 @@
} }
// 获取食堂审领人 // 获取食堂审领人
const getAllUserList = () => { const getAllUserList = () => {
getusersList({page:1,limit:120}).then((res : any) => { getusersList({ page: 1, limit: 120 }).then((res : any) => {
siteUser.value = res.data.data || []; siteUser.value = res.data.data || [];
}).catch(err => { }).catch(err => {
// 如果是4001没有绑定企业账号强制跳转绑定 // 如果是4001没有绑定企业账号强制跳转绑定
@@ -208,36 +217,38 @@
}) })
} }
// 保存 // 保存
const handSave = async() => { const handSave = async () => {
formRef.value.validate().then(() => { formRef.value.validate().then(() => {
if (loading.value) return if (loading.value) return
loading.value = true loading.value = true
addCustomer(formData).then((res: any) => { addCustomer(formData).then((res : any) => {
loading.value = false loading.value = false
if(res.code == 1){ if (res.code == 1) {
redirect({ url: '/addon/erp/pages/base/customer/list' }) redirect({ url: '/addon/erp/pages/base/customer/list' })
} }
}).catch((err) => { }).catch((err) => {
// 如果是4001没有绑定企业账号强制跳转绑定 // 如果是4001没有绑定企业账号强制跳转绑定
if(err.code == 4001){ if (err.code == 4001) {
redirect({ url: '/addon/erp/pages/member/bind' }) redirect({ url: '/addon/erp/pages/member/bind' })
} }
loading.value = false loading.value = false
}) })
}) })
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.form-edit :deep(.u-form-item__body__left__content__label){ .form-edit :deep(.u-form-item__body__left__content__label) {
font-size: 28rpx !important; font-size: 28rpx !important;
} }
.form-edit :deep(.u-form-item__body__right){
display:flex; .form-edit :deep(.u-form-item__body__right) {
display: flex;
align-items: center; align-items: center;
} }
.footer{
.footer {
height: calc(100rpx + var(--top-m) + var(--top-m) + constant(safe-area-inset-bottom)) !important; height: calc(100rpx + var(--top-m) + var(--top-m) + constant(safe-area-inset-bottom)) !important;
height: calc(100rpx + var(--top-m) + var(--top-m) + env(safe-area-inset-bottom)) !important; height: calc(100rpx + var(--top-m) + var(--top-m) + env(safe-area-inset-bottom)) !important;
} }

View File

@@ -34,10 +34,10 @@
{{ t('spec') }}:<text {{ t('spec') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text>
</view> </view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]"> <!-- <view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('inventory') }}:<text {{ t('inventory') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
</view> </view> -->
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]"> <view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('productUnitId') }}:<text {{ t('productUnitId') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text>

View File

@@ -37,10 +37,10 @@
{{ t('spec') }}:<text {{ t('spec') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text>
</view> </view>
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]"> <!-- <view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('inventory') }}:<text {{ t('inventory') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
</view> </view> -->
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]"> <view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
{{ t('productUnitId') }}:<text {{ t('productUnitId') }}:<text
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text> class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text>

View File

@@ -28,7 +28,7 @@
@click="selected.city = item">{{ item.name }}</view> @click="selected.city = item">{{ item.name }}</view>
</view> </view>
<view v-if="areaList.district.length" v-show="currSelect == 'district'"> <view v-if="areaList.district.length" v-show="currSelect == 'district'">
<view v-for="item in areaList.district" class="h-[80rpx] flex items-center " :class="{'text-[var(--primary-color)]': selected.district && selected.district.id == item.id }" <view v-for="item in areaList.district" class="h-[80rpx] flex items-center" :class="{'text-[var(--primary-color)]': selected.district && selected.district.id == item.id }"
@click="selected.district = item">{{ item.name }}</view> @click="selected.district = item">{{ item.name }}</view>
</view> </view>
</view> </view>

View File

@@ -47,7 +47,7 @@
"urlCheck" : true, "urlCheck" : true,
"es6" : true, "es6" : true,
"postcss" : true, "postcss" : true,
"minified" : true "minified" : false
}, },
"usingComponents" : true, "usingComponents" : true,
"permission" : { "permission" : {