feat:新增客户管理页面多语言国际化
This commit is contained in:
1 parent
5c086a32f5
commit
114c630035
12 files changed
+582
-149
No files matched your search
@@ -5,6 +5,10 @@
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, minimum-scale=0.5, maximum-scale=3.0" />
|
||||
<title>Vite + Vue3.0 + TS项目模板</title>
|
||||
<!-- Source Han Sans CN 字体 -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
@@ -25,14 +25,14 @@ html {
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
font-family: $font-family-primary;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.6;
|
||||
color: $text-color-primary;
|
||||
background-color: $background-color-base;
|
||||
|
||||
|
||||
@include mobile {
|
||||
font-size: $font-size-small;
|
||||
line-height: 1.5;
|
||||
@@ -55,6 +55,7 @@ body {
|
||||
--el-color-primary-dark-2: #0e8a71 !important;
|
||||
--el-border-radius-base: 4px;
|
||||
--el-font-size-base: 14px;
|
||||
--el-font-family: #{$font-family-primary};
|
||||
}
|
||||
|
||||
/* 工具类样式 */
|
||||
|
||||
@@ -29,6 +29,9 @@ $font-size-base: 14px; // 保持14px(UI常用)
|
||||
$font-size-small: 12px; // 改为12px
|
||||
$font-size-extra-small: 12px;
|
||||
|
||||
// 字体系列
|
||||
$font-family-primary: 'Noto Sans SC', 'Source Han Sans CN', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
|
||||
// 字体粗细
|
||||
$font-weight-primary: 500;
|
||||
$font-weight-secondary: 400;
|
||||
|
||||
@@ -99,5 +99,137 @@
|
||||
"month": "This Month"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"users": {
|
||||
"title": "System Users",
|
||||
"welcome": "Welcome to the System Users page"
|
||||
},
|
||||
"roles": {
|
||||
"title": "Roles & Permissions",
|
||||
"welcome": "Welcome to the Roles & Permissions page"
|
||||
},
|
||||
"licenses": {
|
||||
"title": "License Management",
|
||||
"welcome": "Welcome to the License Management page"
|
||||
}
|
||||
},
|
||||
"customers": {
|
||||
"title": "Customer Management",
|
||||
"viewCustomer": "View Customer",
|
||||
"addCustomer": "Add New Customer",
|
||||
"editCustomer": "Edit Customer",
|
||||
"actions": {
|
||||
"add": "Add New Customer",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"viewLicense": "View License",
|
||||
"save": "Save",
|
||||
"cancel": "Cancel"
|
||||
},
|
||||
"table": {
|
||||
"customerCode": "Customer Code",
|
||||
"customerName": "Customer Name",
|
||||
"customerType": "Customer Type",
|
||||
"contactPerson": "Contact Person",
|
||||
"email": "Email",
|
||||
"customerLevel": "Customer Level",
|
||||
"status": "Status",
|
||||
"createTime": "Create Time",
|
||||
"operation": "Operation",
|
||||
"loading": "Loading..."
|
||||
},
|
||||
"form": {
|
||||
"basicInfo": "Basic Information",
|
||||
"businessInfo": "Business Information",
|
||||
"customerName": "Customer Name",
|
||||
"customerType": "Customer Type",
|
||||
"customerLevel": "Customer Level",
|
||||
"contactPerson": "Contact Person",
|
||||
"email": "Email",
|
||||
"status": "Status",
|
||||
"phone": "Phone",
|
||||
"address": "Address",
|
||||
"industry": "Industry",
|
||||
"companySize": "Company Size",
|
||||
"businessScope": "Business Scope",
|
||||
"establishedDate": "Established Date",
|
||||
"registrationNumber": "Registration Number",
|
||||
"taxNumber": "Tax Number",
|
||||
"legalRepresentative": "Legal Representative",
|
||||
"website": "Website",
|
||||
"description": "Description",
|
||||
"preferredLicense": "Preferred License",
|
||||
"placeholder": {
|
||||
"enter": "Please enter",
|
||||
"select": "Please select"
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"label": "Filter:",
|
||||
"customerType": "Customer Type",
|
||||
"customerLevel": "Customer Level",
|
||||
"status": "Status"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Search customer code, name, contact, email"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"customerManagement": "Customer Management",
|
||||
"addCustomer": "Add New Customer",
|
||||
"editCustomer": "Edit Customer"
|
||||
},
|
||||
"confirm": {
|
||||
"deleteTitle": "Confirm Delete",
|
||||
"deleteMessage": "Are you sure you want to delete customer \"{name}\"?",
|
||||
"disableTitle": "Confirm Disable",
|
||||
"disableMessage": "Are you sure you want to disable customer \"{name}\"?",
|
||||
"enableTitle": "Confirm Enable",
|
||||
"enableMessage": "Are you sure you want to enable customer \"{name}\"?",
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel"
|
||||
},
|
||||
"message": {
|
||||
"deleteSuccess": "Delete successful",
|
||||
"deleteCancel": "Delete cancelled",
|
||||
"deleteLoading": "Deleting...",
|
||||
"disableLoading": "Disabling...",
|
||||
"enableLoading": "Enabling...",
|
||||
"statusChangeCancel": "{action} cancelled",
|
||||
"loadEnumError": "Failed to load enum data",
|
||||
"getDetailError": "Failed to get customer detail: "
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "Please enter customer name",
|
||||
"typeRequired": "Please select customer type",
|
||||
"levelRequired": "Please select customer level",
|
||||
"contactRequired": "Please enter contact person",
|
||||
"statusRequired": "Please select status",
|
||||
"companySizeRequired": "Please select company size",
|
||||
"emailFormat": "Please enter valid email format",
|
||||
"phoneFormat": "Please enter valid phone format",
|
||||
"websiteFormat": "Please enter valid website format"
|
||||
},
|
||||
"view": {
|
||||
"back": "Back",
|
||||
"statusInfo": "Status Information",
|
||||
"licenseStats": "License Statistics",
|
||||
"creator": "Creator",
|
||||
"createTime": "Create Time",
|
||||
"updater": "Updater",
|
||||
"updateTime": "Update Time",
|
||||
"totalLicenses": "Total Licenses",
|
||||
"activeLicenses": "Active Licenses",
|
||||
"recentLicense": "Recent License",
|
||||
"expiringSoon": "Expiring Soon",
|
||||
"expiringSoonTime": "Expiring Soon Time",
|
||||
"expiredLicenses": "Expired Licenses",
|
||||
"expiredTime": "Expired Time",
|
||||
"noData": "--",
|
||||
"onlineLicense": "Online License",
|
||||
"customerNotExist": "Customer data does not exist"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,5 +99,137 @@
|
||||
"month": "今月"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"users": {
|
||||
"title": "システムユーザー",
|
||||
"welcome": "システムユーザーページへようこそ"
|
||||
},
|
||||
"roles": {
|
||||
"title": "ロールと権限",
|
||||
"welcome": "ロールと権限ページへようこそ"
|
||||
},
|
||||
"licenses": {
|
||||
"title": "ライセンス管理",
|
||||
"welcome": "ライセンス管理ページへようこそ"
|
||||
}
|
||||
},
|
||||
"customers": {
|
||||
"title": "顧客管理",
|
||||
"viewCustomer": "顧客表示",
|
||||
"addCustomer": "新規顧客追加",
|
||||
"editCustomer": "顧客編集",
|
||||
"actions": {
|
||||
"add": "新規顧客追加",
|
||||
"edit": "編集",
|
||||
"delete": "削除",
|
||||
"enable": "有効化",
|
||||
"disable": "無効化",
|
||||
"viewLicense": "ライセンス表示",
|
||||
"save": "保存",
|
||||
"cancel": "キャンセル"
|
||||
},
|
||||
"table": {
|
||||
"customerCode": "顧客コード",
|
||||
"customerName": "顧客名",
|
||||
"customerType": "顧客タイプ",
|
||||
"contactPerson": "担当者",
|
||||
"email": "メール",
|
||||
"customerLevel": "顧客レベル",
|
||||
"status": "ステータス",
|
||||
"createTime": "作成日時",
|
||||
"operation": "操作",
|
||||
"loading": "読み込み中..."
|
||||
},
|
||||
"form": {
|
||||
"basicInfo": "基本情報",
|
||||
"businessInfo": "ビジネス情報",
|
||||
"customerName": "顧客名",
|
||||
"customerType": "顧客タイプ",
|
||||
"customerLevel": "顧客レベル",
|
||||
"contactPerson": "担当者",
|
||||
"email": "メール",
|
||||
"status": "ステータス",
|
||||
"phone": "電話番号",
|
||||
"address": "住所",
|
||||
"industry": "業界",
|
||||
"companySize": "会社規模",
|
||||
"businessScope": "事業範囲",
|
||||
"establishedDate": "設立日",
|
||||
"registrationNumber": "登録番号",
|
||||
"taxNumber": "税務番号",
|
||||
"legalRepresentative": "法定代表者",
|
||||
"website": "ウェブサイト",
|
||||
"description": "説明",
|
||||
"preferredLicense": "優先ライセンス",
|
||||
"placeholder": {
|
||||
"enter": "入力してください",
|
||||
"select": "選択してください"
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"label": "フィルター:",
|
||||
"customerType": "顧客タイプ",
|
||||
"customerLevel": "顧客レベル",
|
||||
"status": "ステータス"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "顧客コード、顧客名、担当者、メールで検索"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"customerManagement": "顧客管理",
|
||||
"addCustomer": "新規顧客追加",
|
||||
"editCustomer": "顧客編集"
|
||||
},
|
||||
"confirm": {
|
||||
"deleteTitle": "削除確認",
|
||||
"deleteMessage": "顧客 \"{name}\" を削除してもよろしいですか?",
|
||||
"disableTitle": "無効化確認",
|
||||
"disableMessage": "顧客 \"{name}\" を無効化してもよろしいですか?",
|
||||
"enableTitle": "有効化確認",
|
||||
"enableMessage": "顧客 \"{name}\" を有効化してもよろしいですか?",
|
||||
"confirm": "確認",
|
||||
"cancel": "キャンセル"
|
||||
},
|
||||
"message": {
|
||||
"deleteSuccess": "削除しました",
|
||||
"deleteCancel": "削除をキャンセルしました",
|
||||
"deleteLoading": "削除中...",
|
||||
"disableLoading": "無効化中...",
|
||||
"enableLoading": "有効化中...",
|
||||
"statusChangeCancel": "{action}をキャンセルしました",
|
||||
"loadEnumError": "列挙データの読み込みに失敗しました",
|
||||
"getDetailError": "顧客詳細の取得に失敗しました:"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "顧客名を入力してください",
|
||||
"typeRequired": "顧客タイプを選択してください",
|
||||
"levelRequired": "顧客レベルを選択してください",
|
||||
"contactRequired": "担当者を入力してください",
|
||||
"statusRequired": "ステータスを選択してください",
|
||||
"companySizeRequired": "会社規模を選択してください",
|
||||
"emailFormat": "正しいメール形式を入力してください",
|
||||
"phoneFormat": "正しい電話番号形式を入力してください",
|
||||
"websiteFormat": "正しいウェブサイト形式を入力してください"
|
||||
},
|
||||
"view": {
|
||||
"back": "戻る",
|
||||
"statusInfo": "ステータス情報",
|
||||
"licenseStats": "ライセンス統計",
|
||||
"creator": "作成者",
|
||||
"createTime": "作成日時",
|
||||
"updater": "更新者",
|
||||
"updateTime": "更新日時",
|
||||
"totalLicenses": "総ライセンス数",
|
||||
"activeLicenses": "アクティブライセンス",
|
||||
"recentLicense": "最近のライセンス",
|
||||
"expiringSoon": "期限近し",
|
||||
"expiringSoonTime": "期限近し日時",
|
||||
"expiredLicenses": "期限切れライセンス",
|
||||
"expiredTime": "期限切れ日時",
|
||||
"noData": "--",
|
||||
"onlineLicense": "オンラインライセンス",
|
||||
"customerNotExist": "顧客データが存在しません"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,5 +99,137 @@
|
||||
"month": "本月"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pages": {
|
||||
"users": {
|
||||
"title": "系统用户",
|
||||
"welcome": "欢迎你来到系统用户页面"
|
||||
},
|
||||
"roles": {
|
||||
"title": "角色权限",
|
||||
"welcome": "欢迎你来到角色权限页面"
|
||||
},
|
||||
"licenses": {
|
||||
"title": "授权管理",
|
||||
"welcome": "欢迎你来到授权管理页面"
|
||||
}
|
||||
},
|
||||
"customers": {
|
||||
"title": "客户管理",
|
||||
"viewCustomer": "查看客户",
|
||||
"addCustomer": "添加新客户",
|
||||
"editCustomer": "编辑客户",
|
||||
"actions": {
|
||||
"add": "添加新客户",
|
||||
"edit": "编辑",
|
||||
"delete": "删除",
|
||||
"enable": "启用",
|
||||
"disable": "禁用",
|
||||
"viewLicense": "查看授权",
|
||||
"save": "保 存",
|
||||
"cancel": "取 消"
|
||||
},
|
||||
"table": {
|
||||
"customerCode": "客户编码",
|
||||
"customerName": "客户名称",
|
||||
"customerType": "客户类型",
|
||||
"contactPerson": "联系人",
|
||||
"email": "邮箱",
|
||||
"customerLevel": "客户等级",
|
||||
"status": "状态",
|
||||
"createTime": "创建时间",
|
||||
"operation": "操作",
|
||||
"loading": "加载中..."
|
||||
},
|
||||
"form": {
|
||||
"basicInfo": "基本信息",
|
||||
"businessInfo": "商业信息",
|
||||
"customerName": "客户名称",
|
||||
"customerType": "客户类型",
|
||||
"customerLevel": "客户等级",
|
||||
"contactPerson": "联系人",
|
||||
"email": "邮箱",
|
||||
"status": "状态",
|
||||
"phone": "联系电话",
|
||||
"address": "地址",
|
||||
"industry": "所属行业",
|
||||
"companySize": "公司规模",
|
||||
"businessScope": "经营范围",
|
||||
"establishedDate": "成立时间",
|
||||
"registrationNumber": "工商注册号",
|
||||
"taxNumber": "税务登记号",
|
||||
"legalRepresentative": "法定代表人",
|
||||
"website": "公司网址",
|
||||
"description": "客户描述",
|
||||
"preferredLicense": "首选授权",
|
||||
"placeholder": {
|
||||
"enter": "请输入",
|
||||
"select": "请选择"
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"label": "筛选:",
|
||||
"customerType": "客户类型",
|
||||
"customerLevel": "客户等级",
|
||||
"status": "状态"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "搜索客户编码、客户名称、联系人、邮箱"
|
||||
},
|
||||
"breadcrumb": {
|
||||
"customerManagement": "客户管理",
|
||||
"addCustomer": "添加新客户",
|
||||
"editCustomer": "编辑客户"
|
||||
},
|
||||
"confirm": {
|
||||
"deleteTitle": "确认删除",
|
||||
"deleteMessage": "确定要删除客户 \"{name}\" 吗?",
|
||||
"disableTitle": "确认禁用",
|
||||
"disableMessage": "确定要禁用客户 \"{name}\" 吗?",
|
||||
"enableTitle": "确认启用",
|
||||
"enableMessage": "确定要启用客户 \"{name}\" 吗?",
|
||||
"confirm": "确定",
|
||||
"cancel": "取消"
|
||||
},
|
||||
"message": {
|
||||
"deleteSuccess": "删除成功",
|
||||
"deleteCancel": "已取消删除",
|
||||
"deleteLoading": "删除中...",
|
||||
"disableLoading": "禁用中...",
|
||||
"enableLoading": "启用中...",
|
||||
"statusChangeCancel": "已取消{action}",
|
||||
"loadEnumError": "加载枚举数据失败",
|
||||
"getDetailError": "获取客户详情失败:"
|
||||
},
|
||||
"validation": {
|
||||
"nameRequired": "请输入客户名称",
|
||||
"typeRequired": "请选择客户类型",
|
||||
"levelRequired": "请选择客户等级",
|
||||
"contactRequired": "请输入联系人",
|
||||
"statusRequired": "请选择状态",
|
||||
"companySizeRequired": "请选择企业规模",
|
||||
"emailFormat": "请输入正确的邮箱格式",
|
||||
"phoneFormat": "请输入正确的手机号码",
|
||||
"websiteFormat": "请输入正确的网址格式"
|
||||
},
|
||||
"view": {
|
||||
"back": "返 回",
|
||||
"statusInfo": "状态信息",
|
||||
"licenseStats": "授权统计",
|
||||
"creator": "创建人",
|
||||
"createTime": "创建时间",
|
||||
"updater": "更新人",
|
||||
"updateTime": "更新时间",
|
||||
"totalLicenses": "总授权数",
|
||||
"activeLicenses": "活跃授权",
|
||||
"recentLicense": "最近授权",
|
||||
"expiringSoon": "即将过期",
|
||||
"expiringSoonTime": "即将过期时间",
|
||||
"expiredLicenses": "过期授权",
|
||||
"expiredTime": "过期时间",
|
||||
"noData": "--",
|
||||
"onlineLicense": "在线授权",
|
||||
"customerNotExist": "客户数据不存在"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,15 +11,15 @@
|
||||
<div class="top-section">
|
||||
<!-- 面包屑导航 -->
|
||||
<div class="breadcrumb">
|
||||
<span class="breadcrumb-item">客户管理</span>
|
||||
<span class="breadcrumb-item">{{ t('customers.breadcrumb.customerManagement') }}</span>
|
||||
<span class="breadcrumb-separator">></span>
|
||||
<span class="breadcrumb-current">{{ isEdit ? '编辑客户' : '添加新客户' }}</span>
|
||||
<span class="breadcrumb-current">{{ isEdit ? t('customers.breadcrumb.editCustomer') : t('customers.breadcrumb.addCustomer') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="form-actions">
|
||||
<el-button @click="handleCancel">取 消</el-button>
|
||||
<el-button type="primary" @click="handleSave" :loading="loading">保 存</el-button>
|
||||
<el-button @click="handleCancel">{{ t('customers.actions.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="handleSave" :loading="loading">{{ t('customers.actions.save') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
<el-form :model="formData" :rules="formRules" ref="formRef" label-position="top">
|
||||
<!-- 基本信息 -->
|
||||
<div class="customer-form">
|
||||
<h3 class="section-title">基本信息</h3>
|
||||
<h3 class="section-title">{{ t('customers.form.basicInfo') }}</h3>
|
||||
|
||||
<!-- Flex布局 - 7个字段横向排列 -->
|
||||
<div class="fields-row-flex">
|
||||
<el-form-item label="客户名称" prop="name" required class="field-item">
|
||||
<el-input v-model="formData.name" placeholder="请输入" />
|
||||
<el-form-item :label="t('customers.form.customerName')" prop="name" required class="field-item">
|
||||
<el-input v-model="formData.name" :placeholder="t('customers.form.placeholder.enter')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="客户类型" prop="type" required class="field-item">
|
||||
<el-select v-model="formData.type" placeholder="请选择" style="width: 100%">
|
||||
<el-form-item :label="t('customers.form.customerType')" prop="type" required class="field-item">
|
||||
<el-select v-model="formData.type" :placeholder="t('customers.form.placeholder.select')" style="width: 100%">
|
||||
<el-option
|
||||
v-for="option in customerTypeOptions"
|
||||
:key="option.key"
|
||||
@@ -47,8 +47,8 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="客户等级" prop="level" required class="field-item">
|
||||
<el-select v-model="formData.level" placeholder="请选择" style="width: 100%">
|
||||
<el-form-item :label="t('customers.form.customerLevel')" prop="level" required class="field-item">
|
||||
<el-select v-model="formData.level" :placeholder="t('customers.form.placeholder.select')" style="width: 100%">
|
||||
<el-option
|
||||
v-for="option in customerLevelOptions"
|
||||
:key="option.key"
|
||||
@@ -58,15 +58,15 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="联系人" prop="contact" required class="field-item">
|
||||
<el-input v-model="formData.contact" placeholder="请输入" />
|
||||
<el-form-item :label="t('customers.form.contactPerson')" prop="contact" required class="field-item">
|
||||
<el-input v-model="formData.contact" :placeholder="t('customers.form.placeholder.enter')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="邮箱" prop="email" class="field-item">
|
||||
<el-input v-model="formData.email" placeholder="请输入" />
|
||||
<el-form-item :label="t('customers.form.email')" prop="email" class="field-item">
|
||||
<el-input v-model="formData.email" :placeholder="t('customers.form.placeholder.enter')" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="状态" prop="status" required class="field-item status-field">
|
||||
<el-form-item :label="t('customers.form.status')" prop="status" required class="field-item status-field">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio
|
||||
v-for="option in statusOptions"
|
||||
@@ -78,26 +78,26 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="联系电话" prop="phone" class="field-item">
|
||||
<el-input v-model="formData.phone" placeholder="请输入" />
|
||||
<el-form-item :label="t('customers.form.phone')" prop="phone" class="field-item">
|
||||
<el-input v-model="formData.phone" :placeholder="t('customers.form.placeholder.enter')" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- Grid布局 - 地址跨列 -->
|
||||
<div class="fields-row-grid">
|
||||
<el-form-item label="地址" prop="address" class="address-field">
|
||||
<el-input v-model="formData.address" placeholder="请输入" />
|
||||
<el-form-item :label="t('customers.form.address')" prop="address" class="address-field">
|
||||
<el-input v-model="formData.address" :placeholder="t('customers.form.placeholder.enter')" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 商业信息 -->
|
||||
<div class="customer-form">
|
||||
<h3 class="section-title">商业信息</h3>
|
||||
<h3 class="section-title">{{ t('customers.form.businessInfo') }}</h3>
|
||||
|
||||
<div class="business-fields">
|
||||
<el-form-item label="企业规模" prop="companySize" required class="company-size-field">
|
||||
<el-select v-model="formData.companySize" placeholder="请选择" style="width: 100%">
|
||||
<el-form-item :label="t('customers.form.companySize')" prop="companySize" required class="company-size-field">
|
||||
<el-select v-model="formData.companySize" :placeholder="t('customers.form.placeholder.select')" style="width: 100%">
|
||||
<el-option
|
||||
v-for="option in companySizeOptions"
|
||||
:key="option.key"
|
||||
@@ -107,12 +107,12 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="客户描述" prop="description" class="description-field">
|
||||
<el-form-item :label="t('customers.form.description')" prop="description" class="description-field">
|
||||
<el-input
|
||||
v-model="formData.description"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入"
|
||||
:placeholder="t('customers.form.placeholder.enter')"
|
||||
:maxlength="500"
|
||||
show-word-limit
|
||||
/>
|
||||
@@ -126,6 +126,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { createCustomer, updateCustomer, getCustomerDetail } from '@/api/customer'
|
||||
import {
|
||||
getCustomerTypeEnums,
|
||||
@@ -159,6 +160,8 @@ const emit = defineEmits<{
|
||||
cancel: []
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const loading = ref(false)
|
||||
|
||||
@@ -195,7 +198,7 @@ const loadEnums = async () => {
|
||||
companySizeOptions.value = sizeRes.data.items
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载枚举数据失败:', error)
|
||||
console.error(t('customers.message.loadEnumError'), error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,28 +219,28 @@ const formData = reactive<CustomerFormData>({
|
||||
// 表单验证规则
|
||||
const formRules: FormRules = {
|
||||
name: [
|
||||
{ required: true, message: '请输入客户名称', trigger: 'blur' }
|
||||
{ required: true, message: t('customers.validation.nameRequired'), trigger: 'blur' }
|
||||
],
|
||||
contact: [
|
||||
{ required: true, message: '请输入联系人', trigger: 'blur' }
|
||||
{ required: true, message: t('customers.validation.contactRequired'), trigger: 'blur' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择客户类型', trigger: 'change' }
|
||||
{ required: true, message: t('customers.validation.typeRequired'), trigger: 'change' }
|
||||
],
|
||||
level: [
|
||||
{ required: true, message: '请选择客户等级', trigger: 'change' }
|
||||
{ required: true, message: t('customers.validation.levelRequired'), trigger: 'change' }
|
||||
],
|
||||
status: [
|
||||
{ required: true, message: '请选择状态', trigger: 'change' }
|
||||
{ required: true, message: t('customers.validation.statusRequired'), trigger: 'change' }
|
||||
],
|
||||
companySize: [
|
||||
{ required: true, message: '请选择企业规模', trigger: 'change' }
|
||||
{ required: true, message: t('customers.validation.companySizeRequired'), trigger: 'change' }
|
||||
],
|
||||
email: [
|
||||
{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
|
||||
{ type: 'email', message: t('customers.validation.emailFormat'), trigger: 'blur' }
|
||||
],
|
||||
phone: [
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: t('customers.validation.phoneFormat'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -266,13 +269,13 @@ const loadCustomerData = async () => {
|
||||
description: customerData.description || ''
|
||||
})
|
||||
} else {
|
||||
ElMessage.error('获取客户详情失败:' + response.message)
|
||||
ElMessage.error(t('customers.message.getDetailError') + response.message)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('获取客户详情失败:', error)
|
||||
console.error('Get customer detail error:', error)
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
if (errorMessage) {
|
||||
ElMessage.error('获取客户详情失败:' + errorMessage)
|
||||
ElMessage.error(t('customers.message.getDetailError') + errorMessage)
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
@@ -321,7 +324,7 @@ const handleSave = async () => {
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('保存失败:', error)
|
||||
console.error('Save failed:', error)
|
||||
// 使用后端返回的错误信息
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
if (errorMessage) {
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
<div class="top-section">
|
||||
<!-- 面包屑导航 -->
|
||||
<div class="breadcrumb">
|
||||
<span class="breadcrumb-item">客户管理</span>
|
||||
<span class="breadcrumb-item">{{ t('customers.breadcrumb.customerManagement') }}</span>
|
||||
<span class="breadcrumb-separator">></span>
|
||||
<span class="breadcrumb-current">查看客户</span>
|
||||
<span class="breadcrumb-current">{{ t('customers.viewCustomer') }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 返回按钮 -->
|
||||
<div class="form-actions">
|
||||
<el-button @click="handleBack">返 回</el-button>
|
||||
<el-button @click="handleBack">{{ t('customers.view.back') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,83 +26,83 @@
|
||||
<div class="customer-view" v-loading="loading">
|
||||
<!-- 基本信息卡片 -->
|
||||
<div class="info-card basic-info">
|
||||
<h3 class="section-title">基本信息</h3>
|
||||
<h3 class="section-title">{{ t('customers.form.basicInfo') }}</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="label">客户名称:</span>
|
||||
<span class="value">{{ customerData.name || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.customerName') }}:</span>
|
||||
<span class="value">{{ customerData.name || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">客户类型:</span>
|
||||
<span class="label">{{ t('customers.form.customerType') }}:</span>
|
||||
<span class="value">{{ getCustomerTypeLabel(customerData.type) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">客户等级:</span>
|
||||
<span class="label">{{ t('customers.form.customerLevel') }}:</span>
|
||||
<span class="value">{{ getCustomerLevelLabel(customerData.level) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">联系人:</span>
|
||||
<span class="value">{{ customerData.contact || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.contactPerson') }}:</span>
|
||||
<span class="value">{{ customerData.contact || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">邮箱:</span>
|
||||
<span class="value">{{ customerData.email || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.email') }}:</span>
|
||||
<span class="value">{{ customerData.email || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">状态:</span>
|
||||
<span class="label">{{ t('customers.form.status') }}:</span>
|
||||
<span class="value">{{ getStatusLabel(customerData.status) }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">联系电话:</span>
|
||||
<span class="value">{{ customerData.phone || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.phone') }}:</span>
|
||||
<span class="value">{{ customerData.phone || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item full-width">
|
||||
<span class="label">地址:</span>
|
||||
<span class="value">{{ customerData.address || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.address') }}:</span>
|
||||
<span class="value">{{ customerData.address || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 商业信息卡片 -->
|
||||
<div class="info-card business-info">
|
||||
<h3 class="section-title">商业信息</h3>
|
||||
<h3 class="section-title">{{ t('customers.form.businessInfo') }}</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="label">企业规模:</span>
|
||||
<span class="value">{{ enumLabels.companySize || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.companySize') }}:</span>
|
||||
<span class="value">{{ enumLabels.companySize || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item full-width">
|
||||
<span class="label">首选授权:</span>
|
||||
<span class="value">{{ customerData.preferredLicense || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.preferredLicense') }}:</span>
|
||||
<span class="value">{{ customerData.preferredLicense || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="info-item full-width">
|
||||
<span class="label">客户描述:</span>
|
||||
<span class="value description">{{ customerData.description || '--' }}</span>
|
||||
<span class="label">{{ t('customers.form.description') }}:</span>
|
||||
<span class="value description">{{ customerData.description || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 状态信息卡片 -->
|
||||
<div class="info-card status-info">
|
||||
<h3 class="section-title">状态信息</h3>
|
||||
<h3 class="section-title">{{ t('customers.view.statusInfo') }}</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item inline-group full-width">
|
||||
<div class="inline-pair">
|
||||
<span class="label">创建人:</span>
|
||||
<span class="value">{{ customerData.statusRecords?.[0]?.user || '--' }}</span>
|
||||
<span class="label">{{ t('customers.view.creator') }}:</span>
|
||||
<span class="value">{{ customerData.statusRecords?.[0]?.user || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="inline-pair">
|
||||
<span class="label">创建时间:</span>
|
||||
<span class="label">{{ t('customers.view.createTime') }}:</span>
|
||||
<span class="value">{{ formatDate(customerData.statusRecords?.[0]?.time) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item inline-group full-width">
|
||||
<div class="inline-pair">
|
||||
<span class="label">更新人:</span>
|
||||
<span class="value">{{ customerData.statusRecords?.[1]?.user || '--' }}</span>
|
||||
<span class="label">{{ t('customers.view.updater') }}:</span>
|
||||
<span class="value">{{ customerData.statusRecords?.[1]?.user || t('customers.view.noData') }}</span>
|
||||
</div>
|
||||
<div class="inline-pair">
|
||||
<span class="label">更新时间:</span>
|
||||
<span class="label">{{ t('customers.view.updateTime') }}:</span>
|
||||
<span class="value">{{ formatDate(customerData.statusRecords?.[1]?.time) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,37 +111,37 @@
|
||||
|
||||
<!-- 授权统计卡片 -->
|
||||
<div class="info-card license-stats">
|
||||
<h3 class="section-title">授权统计</h3>
|
||||
<h3 class="section-title">{{ t('customers.view.licenseStats') }}</h3>
|
||||
<div class="info-grid">
|
||||
<div class="info-item">
|
||||
<span class="label">总授权数:</span>
|
||||
<span class="label">{{ t('customers.view.totalLicenses') }}:</span>
|
||||
<span class="value">{{ customerData.totalLicenses || 0 }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">活跃授权:</span>
|
||||
<span class="label">{{ t('customers.view.activeLicenses') }}:</span>
|
||||
<span class="value">{{ customerData.activeLicenses || 0 }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">最近授权:</span>
|
||||
<span class="label">{{ t('customers.view.recentLicense') }}:</span>
|
||||
<span class="value">{{ formatDate(customerData.latestLicenseTime) }}</span>
|
||||
</div>
|
||||
<div class="info-item inline-group full-width">
|
||||
<div class="inline-pair">
|
||||
<span class="label">即将过期:</span>
|
||||
<span class="label">{{ t('customers.view.expiringSoon') }}:</span>
|
||||
<span class="value">{{ customerData.expiringSoonLicenses || 0 }}</span>
|
||||
</div>
|
||||
<div class="inline-pair">
|
||||
<span class="label">即将过期时间:</span>
|
||||
<span class="label">{{ t('customers.view.expiringSoonTime') }}:</span>
|
||||
<span class="value">{{ formatDate(customerData.expiringSoonTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-item inline-group full-width">
|
||||
<div class="inline-pair">
|
||||
<span class="label">过期授权:</span>
|
||||
<span class="label">{{ t('customers.view.expiredLicenses') }}:</span>
|
||||
<span class="value">{{ customerData.expiredLicenses || 0 }}</span>
|
||||
</div>
|
||||
<div class="inline-pair">
|
||||
<span class="label">过期时间:</span>
|
||||
<span class="label">{{ t('customers.view.expiredTime') }}:</span>
|
||||
<span class="value">{{ formatDate(customerData.expiredTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -154,6 +154,7 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getCustomerDetail } from '@/api/customer'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
interface StatusRecord {
|
||||
action: string
|
||||
@@ -191,6 +192,7 @@ const emit = defineEmits<{
|
||||
back: []
|
||||
}>()
|
||||
|
||||
const { t } = useI18n()
|
||||
const loading = ref(false)
|
||||
const customerData = ref<Partial<CustomerViewData>>({})
|
||||
|
||||
@@ -213,7 +215,7 @@ const fetchCustomerDetail = async () => {
|
||||
const customer = response.data
|
||||
|
||||
if (!customer) {
|
||||
ElMessage.error('客户数据不存在')
|
||||
ElMessage.error(t('customers.view.customerNotExist'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -236,16 +238,16 @@ const fetchCustomerDetail = async () => {
|
||||
level: customer.customer_level,
|
||||
status: customer.status,
|
||||
companySize: customer.company_size || '',
|
||||
preferredLicense: '在线授权', // 暂时写死,等后端添加字段
|
||||
preferredLicense: t('customers.view.onlineLicense'), // 暂时写死,等后端添加字段
|
||||
description: customer.description || '',
|
||||
statusRecords: [
|
||||
{
|
||||
action: '创建人',
|
||||
action: t('customers.view.creator'),
|
||||
user: customer.created_by,
|
||||
time: customer.created_at
|
||||
},
|
||||
{
|
||||
action: '更新人',
|
||||
action: t('customers.view.updater'),
|
||||
user: customer.updated_by,
|
||||
time: customer.updated_at
|
||||
}
|
||||
@@ -260,7 +262,7 @@ const fetchCustomerDetail = async () => {
|
||||
expiredTime: undefined
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('获取客户详情失败:', error)
|
||||
console.error('Get customer detail failed:', error)
|
||||
// 使用后端返回的错误信息
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
if (errorMessage) {
|
||||
@@ -278,26 +280,26 @@ const handleBack = () => {
|
||||
|
||||
// 获取客户类型标签
|
||||
const getCustomerTypeLabel = (type: string | undefined) => {
|
||||
if (!type) return '--'
|
||||
return enumLabels.value.customerType || '--'
|
||||
if (!type) return t('customers.view.noData')
|
||||
return enumLabels.value.customerType || t('customers.view.noData')
|
||||
}
|
||||
|
||||
// 获取客户等级标签
|
||||
const getCustomerLevelLabel = (level: string | undefined) => {
|
||||
if (!level) return '--'
|
||||
return enumLabels.value.customerLevel || '--'
|
||||
if (!level) return t('customers.view.noData')
|
||||
return enumLabels.value.customerLevel || t('customers.view.noData')
|
||||
}
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusLabel = (status: string | undefined) => {
|
||||
if (!status) return '--'
|
||||
return enumLabels.value.status || '--'
|
||||
if (!status) return t('customers.view.noData')
|
||||
return enumLabels.value.status || t('customers.view.noData')
|
||||
}
|
||||
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (date: string | undefined) => {
|
||||
if (!date) return '--'
|
||||
if (!date) return t('customers.view.noData')
|
||||
return new Date(date).toLocaleString('zh-CN')
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!-- 左侧操作区域 -->
|
||||
<div class="left-actions">
|
||||
<el-button type="primary" class="add-customer-btn" @click="handleAddCustomer">
|
||||
添加新客户
|
||||
{{ t('customers.actions.add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
<div class="right-actions">
|
||||
<!-- 筛选区域 -->
|
||||
<div class="filter-section">
|
||||
<span class="filter-label">筛选:</span>
|
||||
<span class="filter-label">{{ t('customers.filter.label') }}</span>
|
||||
<el-select
|
||||
v-model="filterCustomerType"
|
||||
placeholder="客户类型"
|
||||
:placeholder="t('customers.filter.customerType')"
|
||||
class="filter-select"
|
||||
clearable
|
||||
@change="handleFilterChange"
|
||||
@@ -40,7 +40,7 @@
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="filterCustomerLevel"
|
||||
placeholder="客户等级"
|
||||
:placeholder="t('customers.filter.customerLevel')"
|
||||
class="filter-select"
|
||||
clearable
|
||||
@change="handleFilterChange"
|
||||
@@ -54,7 +54,7 @@
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="filterStatus"
|
||||
placeholder="状态"
|
||||
:placeholder="t('customers.filter.status')"
|
||||
class="filter-select"
|
||||
clearable
|
||||
@change="handleFilterChange"
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="search-section">
|
||||
<el-input
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索客户编码、客户名称、联系人、邮箱"
|
||||
:placeholder="t('customers.search.placeholder')"
|
||||
class="search-input"
|
||||
>
|
||||
<template #append>
|
||||
@@ -89,7 +89,7 @@
|
||||
<el-table
|
||||
:data="tableData"
|
||||
v-loading="loading"
|
||||
element-loading-text="加载中..."
|
||||
:element-loading-text="t('customers.table.loading')"
|
||||
stripe
|
||||
border
|
||||
style="width: 100%;"
|
||||
@@ -97,51 +97,51 @@
|
||||
:row-style="getRowStyle"
|
||||
:max-height="'calc(100vh - 280px)'"
|
||||
>
|
||||
<el-table-column prop="customer_code" label="客户编码" :width="170" show-overflow-tooltip align="left">
|
||||
<el-table-column prop="customer_code" :label="t('customers.table.customerCode')" :width="170" show-overflow-tooltip align="left">
|
||||
<template #default="scope">
|
||||
<span class="customer-code" style="white-space: nowrap; overflow: visible; text-overflow: initial;">{{ scope.row.customer_code }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="customer_name" label="客户名称" :width="180" show-overflow-tooltip align="center">
|
||||
<el-table-column prop="customer_name" :label="t('customers.table.customerName')" :width="180" show-overflow-tooltip align="center">
|
||||
<template #default="scope">
|
||||
<span class="ellipsis-text">{{ scope.row.customer_name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="customer_type_display" label="客户类型" :width="130" align="center">
|
||||
<el-table-column prop="customer_type_display" :label="t('customers.table.customerType')" :width="130" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="contact_person" label="联系人" :width="140" align="center" />
|
||||
<el-table-column prop="email" label="邮箱" :width="160" show-overflow-tooltip align="center">
|
||||
<el-table-column prop="contact_person" :label="t('customers.table.contactPerson')" :width="140" align="center" />
|
||||
<el-table-column prop="email" :label="t('customers.table.email')" :width="160" show-overflow-tooltip align="center">
|
||||
<template #default="scope">
|
||||
<span class="ellipsis-text">{{ scope.row.email }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="customer_level_display" label="客户等级" :width="130" align="center">
|
||||
<el-table-column prop="customer_level_display" :label="t('customers.table.customerLevel')" :width="130" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="status_display" label="状态" :width="100" align="center">
|
||||
<el-table-column prop="status_display" :label="t('customers.table.status')" :width="100" align="center">
|
||||
<template #default="scope">
|
||||
<div class="status-tag" :class="getStatusClass(scope.row.status)">
|
||||
{{scope.row.status_display}}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" :width="135" align="center">
|
||||
<el-table-column :label="t('customers.table.createTime')" :width="140" align="center">
|
||||
<template #default="scope">
|
||||
{{ formatDate(scope.row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" :width="340" fixed="right" class-name="action-column" align="center">
|
||||
<el-table-column :label="t('customers.table.operation')" fixed="right" class-name="action-column" align="center">
|
||||
<template #default="scope">
|
||||
<div class="action-buttons">
|
||||
<button class="action-btn primary" @click="handleViewLicense(scope.row)">查看授权</button>
|
||||
<button class="action-btn primary" @click="handleEdit(scope.row)">编辑</button>
|
||||
<button class="action-btn primary" @click="handleViewLicense(scope.row)">{{ t('customers.actions.viewLicense') }}</button>
|
||||
<button class="action-btn primary" @click="handleEdit(scope.row)">{{ t('customers.actions.edit') }}</button>
|
||||
<button
|
||||
class="action-btn"
|
||||
:class="scope.row.status === 'active' ? 'warning' : 'success'"
|
||||
@click="handleDisable(scope.row)"
|
||||
>
|
||||
{{ scope.row.status === 'active' ? '禁用' : '启用' }}
|
||||
{{ scope.row.status === 'active' ? t('customers.actions.disable') : t('customers.actions.enable') }}
|
||||
</button>
|
||||
<button class="action-btn danger" @click="handleDelete(scope.row)">删除</button>
|
||||
<button class="action-btn danger" @click="handleDelete(scope.row)">{{ t('customers.actions.delete') }}</button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -191,6 +191,7 @@ import CustomerForm from './CustomerForm.vue'
|
||||
import CustomerView from './CustomerView.vue'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElMessageBox, ElLoading } from 'element-plus'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import {
|
||||
getCustomers,
|
||||
deleteCustomer,
|
||||
@@ -207,6 +208,7 @@ import {
|
||||
|
||||
// Customer类型已从API文件导入
|
||||
|
||||
const { t } = useI18n()
|
||||
const searchKeyword = ref('')
|
||||
const filterCustomerType = ref('')
|
||||
const filterCustomerLevel = ref('')
|
||||
@@ -248,15 +250,15 @@ const loadEnums = async () => {
|
||||
statusOptions.value = statusRes.data.items
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载枚举数据失败:', error)
|
||||
console.error(t('customers.message.loadEnumError'), error)
|
||||
}
|
||||
}
|
||||
|
||||
// 页面标题
|
||||
const getPageTitle = () => {
|
||||
if (showCustomerView.value) return '查看客户'
|
||||
if (showCustomerForm.value) return isEditMode.value ? '编辑客户' : '添加新客户'
|
||||
return '客户管理'
|
||||
if (showCustomerView.value) return t('customers.viewCustomer')
|
||||
if (showCustomerForm.value) return isEditMode.value ? t('customers.editCustomer') : t('customers.addCustomer')
|
||||
return t('customers.title')
|
||||
}
|
||||
|
||||
// 时间格式化函数
|
||||
@@ -302,7 +304,7 @@ const loadData = async () => {
|
||||
total.value = 0
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('加载数据错误:', error)
|
||||
console.error('Load data error:', error)
|
||||
|
||||
// 使用后端返回的错误信息
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
@@ -347,22 +349,28 @@ const handleEdit = (row: Customer) => {
|
||||
|
||||
const handleDisable = async (row: Customer) => {
|
||||
const newStatus = row.status === 'active' ? 'disabled' : 'active'
|
||||
const actionText = newStatus === 'disabled' ? '禁用' : '启用'
|
||||
const actionText = newStatus === 'disabled' ? t('customers.actions.disable') : t('customers.actions.enable')
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要${actionText}客户 "${row.customer_name}" 吗?`,
|
||||
`确认${actionText}`,
|
||||
newStatus === 'disabled'
|
||||
? t('customers.confirm.disableMessage', { name: row.customer_name })
|
||||
: t('customers.confirm.enableMessage', { name: row.customer_name }),
|
||||
newStatus === 'disabled'
|
||||
? t('customers.confirm.disableTitle')
|
||||
: t('customers.confirm.enableTitle'),
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonText: t('customers.confirm.confirm'),
|
||||
cancelButtonText: t('customers.confirm.cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: `${actionText}中...`,
|
||||
text: newStatus === 'disabled'
|
||||
? t('customers.message.disableLoading')
|
||||
: t('customers.message.enableLoading'),
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
@@ -377,7 +385,7 @@ const handleDisable = async (row: Customer) => {
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`${actionText}错误:`, error)
|
||||
console.error(`${actionText} error:`, error)
|
||||
|
||||
// 使用后端返回的错误信息
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
@@ -388,7 +396,7 @@ const handleDisable = async (row: Customer) => {
|
||||
loadingInstance.close()
|
||||
}
|
||||
} catch {
|
||||
ElMessage.info(`已取消${actionText}`)
|
||||
ElMessage.info(t('customers.message.statusChangeCancel', { action: actionText }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,18 +422,18 @@ const handleViewLicense = (row: Customer) => {
|
||||
const handleDelete = async (row: Customer) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除客户 "${row.customer_name}" 吗?`,
|
||||
'确认删除',
|
||||
t('customers.confirm.deleteMessage', { name: row.customer_name }),
|
||||
t('customers.confirm.deleteTitle'),
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
confirmButtonText: t('customers.confirm.confirm'),
|
||||
cancelButtonText: t('customers.confirm.cancel'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: '删除中...',
|
||||
text: t('customers.message.deleteLoading'),
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
|
||||
@@ -440,7 +448,7 @@ const handleDelete = async (row: Customer) => {
|
||||
ElMessage.error(response.message)
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('删除错误:', error)
|
||||
console.error('Delete error:', error)
|
||||
|
||||
// 使用后端返回的错误信息
|
||||
let errorMessage = error.backendMessage || error.response?.data?.message || error.message
|
||||
@@ -451,14 +459,14 @@ const handleDelete = async (row: Customer) => {
|
||||
loadingInstance.close()
|
||||
}
|
||||
} catch {
|
||||
ElMessage.info('已取消删除')
|
||||
ElMessage.info(t('customers.message.deleteCancel'))
|
||||
}
|
||||
}
|
||||
|
||||
// 处理客户表单操作
|
||||
const handleFormSave = async (data: any) => {
|
||||
// 这里处理保存逻辑
|
||||
console.log('保存客户数据:', data)
|
||||
console.log('Save customer data:', data)
|
||||
showCustomerForm.value = false
|
||||
await loadData() // 重新加载数据
|
||||
}
|
||||
@@ -645,8 +653,9 @@ onMounted(async () => {
|
||||
width: 100%;
|
||||
height: 100%; // 占满表格容器高度
|
||||
position: relative;
|
||||
overflow: auto; // 启用滚动以支持固定列
|
||||
@include smooth-scroll;
|
||||
|
||||
|
||||
@include mobile {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
@@ -662,7 +671,7 @@ onMounted(async () => {
|
||||
.el-table__header-wrapper,
|
||||
.el-table__body-wrapper {
|
||||
width: 100% !important;
|
||||
overflow-x: hidden !important; /* 防止水平滚动条影响对齐 */
|
||||
overflow-x: auto !important; /* 允许水平滚动以支持固定列 */
|
||||
}
|
||||
|
||||
.el-table__body-wrapper {
|
||||
@@ -810,6 +819,8 @@ onMounted(async () => {
|
||||
.action-buttons {
|
||||
gap: 8px; // 改为8px符合8px栅格
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
@@ -914,6 +925,8 @@ onMounted(async () => {
|
||||
|
||||
.action-buttons {
|
||||
gap: 0.42vw; /* 8px/1920 = 0.42vw */
|
||||
justify-content: center;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
@@ -958,10 +971,10 @@ onMounted(async () => {
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
/* 确保操作列在桌面端的正确宽度 */
|
||||
/* 操作列自适应宽度 */
|
||||
.action-column {
|
||||
width: 17.708vw !important; /* 300px/1920 = 15.625vw */
|
||||
min-width: 17.708vw !important;
|
||||
width: auto !important;
|
||||
min-width: max-content !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,10 +1070,10 @@ onMounted(async () => {
|
||||
padding: 8px 12px !important;
|
||||
}
|
||||
|
||||
/* 移动端操作列宽度修复 */
|
||||
/* 移动端操作列自适应宽度 */
|
||||
.action-column {
|
||||
width: 160px !important;
|
||||
min-width: 160px !important;
|
||||
width: auto !important;
|
||||
min-width: max-content !important;
|
||||
}
|
||||
}
|
||||
/* 设置表格容器 */
|
||||
@@ -1441,10 +1454,11 @@ onMounted(async () => {
|
||||
.action-buttons {
|
||||
gap: $spacing-small;
|
||||
padding: $spacing-base 0;
|
||||
width: 100%;
|
||||
width: auto;
|
||||
min-width: max-content;
|
||||
|
||||
@include flex-center-vertical;
|
||||
justify-content: flex-start;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
overflow: visible;
|
||||
|
||||
@@ -1473,10 +1487,11 @@ onMounted(async () => {
|
||||
font-weight: $font-weight-primary;
|
||||
line-height: 20px; // 改为20px符合8px栅格
|
||||
flex-shrink: 0;
|
||||
width: auto;
|
||||
min-width: fit-content;
|
||||
white-space: nowrap;
|
||||
|
||||
@include button-base;
|
||||
@include text-ellipsis;
|
||||
|
||||
@include mobile {
|
||||
flex: 0 0 calc(50% - #{math.div($spacing-extra-small, 2)}) !important;
|
||||
|
||||
@@ -7,16 +7,19 @@
|
||||
* @Description: 授权管理页面
|
||||
-->
|
||||
<template>
|
||||
<Layout app-name="Cedar-V" page-title="授权管理">
|
||||
<Layout app-name="Cedar-V" :page-title="t('pages.licenses.title')">
|
||||
<!-- 页面内容 -->
|
||||
<div class="content-container">
|
||||
<h1>欢迎你来到授权管理页面</h1>
|
||||
<h1>{{ t('pages.licenses.welcome') }}</h1>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Layout from '@/components/common/layout/Layout.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -7,16 +7,19 @@
|
||||
* @Description: 角色权限页面
|
||||
-->
|
||||
<template>
|
||||
<Layout app-name="Cedar-V" page-title="角色权限">
|
||||
<Layout app-name="Cedar-V" :page-title="t('pages.roles.title')">
|
||||
<!-- 页面内容 -->
|
||||
<div class="content-container">
|
||||
<h1>欢迎你来到角色权限页面</h1>
|
||||
<h1>{{ t('pages.roles.welcome') }}</h1>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Layout from '@/components/common/layout/Layout.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -7,16 +7,19 @@
|
||||
* @Description: 系统用户页面
|
||||
-->
|
||||
<template>
|
||||
<Layout app-name="Cedar-V" page-title="系统用户">
|
||||
<Layout app-name="Cedar-V" :page-title="t('pages.users.title')">
|
||||
<!-- 页面内容 -->
|
||||
<div class="content-container">
|
||||
<h1>欢迎你来到系统用户页面</h1>
|
||||
<h1>{{ t('pages.users.welcome') }}</h1>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Layout from '@/components/common/layout/Layout.vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in new issue
Block a user