csm xiugai

master
2358328281@qq.com 5 days ago
parent d3248a3dae
commit f29c3dc589

@ -133,6 +133,7 @@ export default {
confirmPassword: 'Confirm Password',
hospital: 'Hospital Name',
hospitalName: 'Hospital Name',
hospitalSearch: 'Hospital Name',
contact: 'Contact',
contactPerson: 'Contact Person',
contactDept: 'Contact Department',
@ -148,6 +149,7 @@ export default {
acceptanceReportTip: 'Support uploading PDF format files (required)',
account: 'Account',
accountType: 'Account Type',
nameAccount: 'Name/Account',
password: 'Password',
gender: 'Gender',
role: 'Role',
@ -176,6 +178,7 @@ export default {
search: 'Please input',
keyword: 'Search title/ticket no.',
account: 'Enter account',
nameOrAccount: 'Search by name or account',
password: 'Enter password',
newPassword: 'Enter new password (at least 6 chars)',
confirmPassword: 'Confirm new password',
@ -199,6 +202,7 @@ export default {
cancelSuccess: 'Ticket cancelled successfully!',
closeSuccess: 'Ticket closed successfully!',
passwordChangeSuccess: 'Password changed successfully!',
statusChangeSuccess: 'Status changed successfully!',
languageChangeSuccess: 'Language changed successfully!',
themeChangeSuccess: 'Theme changed successfully!',
hospitalAddSuccess: 'Hospital added successfully!',

@ -1,473 +1,477 @@
export default {
// 公共
common: {
confirm: '确认',
cancel: '取消',
save: '保存',
submit: '提交',
reset: '重置',
query: '查询',
search: '搜索',
add: '添加',
edit: '编辑',
delete: '删除',
view: '查看',
close: '关闭',
back: '返回',
export: '导出',
download: '下载',
upload: '上传',
more: '更多',
all: '全部',
yes: '是',
no: '否',
enabled: '启用',
disabled: '禁用',
pleaseSelect: '请选择',
pleaseInput: '请输入',
success: '成功',
failed: '失败',
operating: '操作',
remark: '备注',
time: '时间',
today: '今日',
yesterday: '昨日',
thisWeek: '本周',
thisMonth: '本月',
thisQuarter: '本季度',
thisYear: '本年',
customDate: '自定义日期',
startDate: '开始日期',
endDate: '结束日期',
language: '语言',
},
// 登录页
login: {
title: '欢迎登录',
name: '康策智能CSM系统',
headerTitle: '康策智能CSM系统',
userName: '请输入账号',
passWord: '请输入密码',
code: '请输入验证码',
jizhu: '记住账号',
denglu: '登 录',
copyright: '上海康策软件有限公司版权所有',
hotline: '服务热线021-60713139',
loginSuccess: '登录成功',
loginFailed: '登录失败',
unknownUserType: '未知用户类型,无法登录',
pleaseEnterUserName: '请输入账号',
pleaseEnterPassWord: '请输入密码',
languageLabel: '语言:',
},
// 导航菜单
nav: {
workbench: '我的工作台',
submit: '我的工单',
points: '我的积分',
quickSubmit: '快速提交',
workorders: '服务工单',
reports: '服务报告',
hospitals: '医院信息',
customer: '客户服务',
managerPoints: '客户经理积分',
account: '账号管理',
grades: '绩效管理',
},
// 页面标题
title: {
workbench: '我的工作台',
submit: '我的工单',
points: '我的积分',
workorders: '服务工单',
reports: '服务报告',
hospitals: '医院信息',
customer: '客户服务',
managerPoints: '客户经理积分',
account: '账号管理',
grades: '绩效管理',
changePassword: '修改密码',
},
// 按钮文本
btn: {
quickSubmit: '快速提交',
view: '查看',
edit: '编辑',
cancel: '取消',
close: '关闭',
detail: '详情',
process: '处理',
submit: '提交工单',
save: '保存修改',
cancelModal: '取消',
saveChange: '保存修改',
query: '查询',
reset: '重置',
export: '导出',
download: '下载',
upload: '上传',
generate: '生成',
add: '添加',
delete: '删除',
addOrder: '+ 新建工单',
addHospital: '+ 添加医院',
addAccount: '+ 添加账号',
quickAddOrder: '+ 快速提交工单',
back: '← 返回',
preview: '查看报告',
downloadPdf: '下载PDF报告',
confirm: '确认修改',
downloadReport: '下载报告',
},
// 表单标签
label: {
title: '问题名称',
description: '问题描述',
attachment: '附件',
dept: '提出科室',
name: '提出人员',
priority: '优先级',
type: '服务类型',
oldPassword: '原密码',
newPassword: '新密码',
confirmPassword: '确认密码',
hospital: '医院名称',
hospitalName: '医院名称',
contact: '联系人',
contactPerson: '联系人',
contactDept: '联系科室',
contactPosition: '职务',
contactPhone: '联系电话',
category: '客户分类',
signDate: '签约时间',
acceptDate: '验收时间',
years: '年限',
maintenanceEndDate: '维保截止时间',
manager: '客户经理',
acceptanceReport: '验收报告',
acceptanceReportTip: '支持上传PDF格式文件必填',
account: '账号',
accountType: '账号类型',
password: '密码',
gender: '性别',
role: '角色',
status: '状态',
renewal: '续保完成',
contractSigned: '合同签署',
paymentPaid: '款项支付',
visited: '回访状态',
visitResult: '回访结果',
createTime: '创建时间',
colorTag: '颜色标签',
currentPassword: '当前密码',
},
// 表单 placeholder
placeholder: {
title: '请输入问题名称',
description: '请详细描述问题,并可以编辑器直接贴图',
dept: '请输入提出科室',
name: '请输入提出人员',
type: '请选择服务类型',
hospital: '请输入医院名称',
contactPerson: '请输入联系人',
contactDept: '请输入联系科室',
contactPosition: '请输入职务',
contactPhone: '请输入联系电话',
search: '请输入',
keyword: '搜索标题/工单号',
account: '请输入账号',
password: '请输入密码',
newPassword: '请输入新密码至少6位',
confirmPassword: '请再次输入新密码',
currentPassword: '请输入当前密码',
remark: '请输入备注信息...',
},
// 提示消息
msg: {
pleaseInputTitle: '请输入问题名称',
pleaseInputDescription: '请输入问题描述',
pleaseSelectPriority: '请选择优先级',
pleaseSelectType: '请选择服务类型',
pleaseSelectHospital: '请选择医院',
pleaseInputDept: '请输入提出科室',
pleaseInputName: '请输入提出人员',
passwordTooShort: '新密码至少需要6位',
passwordMismatch: '两次输入的新密码不一致!',
pleaseFillRequired: '请填写必填项!',
submitSuccess: '工单提交成功!',
editSuccess: '工单修改成功!',
cancelSuccess: '工单已成功取消!',
closeSuccess: '工单已成功关闭!',
passwordChangeSuccess: '密码修改成功!',
languageChangeSuccess: '语言切换成功!',
themeChangeSuccess: '主题切换成功!',
hospitalAddSuccess: '医院添加成功!',
hospitalEditSuccess: '医院信息修改成功!',
accountAddSuccess: '账号添加成功!',
accountEditSuccess: '账号更新成功!',
passwordResetSuccess: '密码重置成功!',
reportGenerateSuccess: '报告生成成功!',
confirmCancelOrder: '确定要取消工单 {orderId} 吗?取消后将无法恢复。',
confirmCloseOrder: '确定要关闭工单 {orderId} 吗?',
},
// 统计
stat: {
total: '累计提交工单',
completed: '已完成工单',
pending: '待处理工单',
highPriority: '高优先级工单',
totalOrders: '总工单',
pendingOrders: '待处理',
completedOrders: '已完成',
highPriorityOrders: '高优先级',
high: '高优先级',
medium: '中优先级',
low: '低优先级',
mediumPriority: '中优先级',
lowPriority: '低优先级',
processing: '处理中',
},
// 表格列
table: {
id: '工单号',
priority: '优先级',
title: '问题名称',
type: '服务类型',
status: '状态',
time: '提交时间',
submitter: '提交人',
action: '操作',
hospital: '医院名称',
handler: '处理人',
handleTime: '处理时间',
handleDesc: '处理说明',
registrar: '登记人',
dept: '提出科室',
category: '客户分类',
contact: '联系人',
phone: '联系电话',
manager: '客户经理',
signDate: '签约日期',
usageYears: '客户使用年限',
maintenanceEnd: '维保截止时间',
acceptanceReport: '验收报告',
account: '账号',
name: '姓名',
gender: '性别',
role: '角色',
createTime: '创建时间',
hospitalName: '医院名称',
},
// 状态
status: {
pending: '待处理',
processing: '处理中',
completed: '已完成',
closed: '已关闭',
active: '活跃',
inactive: '不活跃',
normal: '正常',
warning: '预警',
urgent: '紧急',
expired: '已过期',
renewed: '已续保',
notRenewed: '未续保',
paid: '已付款',
notPaid: '未付款',
},
// 优先级
priority: {
high: '🔴 高',
medium: '🟠 中',
low: '🟢 低',
},
// 类型
type: {
issue: '故障问题',
consult: '使用咨询',
feature: '功能需求',
other: '其他',
},
// 图表
chart: {
title: '工单趋势',
submit: '提交工单',
complete: '完成工单',
bar: '柱状图',
line: '折线图',
},
// 日期按钮
dateBtn: {
thisMonth: '本月',
thisQuarter: '本季度',
thisYear: '本年',
customDate: '自定义日期',
},
// 主题
theme: {
blue: '穹宇蓝',
purple: '星轨紫',
green: '青峦绿',
title: '更换主题',
},
// 语言
languageSwitch: {
title: '更换语言',
zhCN: '中文简体',
zhTW: '中文繁体',
enUS: 'English',
},
// 模态框
modal: {
detail: '工单详情',
edit: '编辑工单',
submit: '快速提交工单',
changePassword: '修改密码',
changeTheme: '更换主题',
changeLanguage: '更换语言',
addAccount: '添加账号',
editAccount: '编辑账号',
resetPassword: '重置密码',
addHospital: '添加医院',
editHospital: '编辑医院',
detailHospital: '医院详情',
generateReport: '生成服务报告',
},
// 用户菜单
userMenu: {
changePassword: '修改密码',
changeTheme: '更换主题',
changeLanguage: '更换语言',
logout: '退出登录',
},
// 客户分类
category: {
A: 'A类活跃',
B: 'B类不活跃',
C: 'C类待挽回',
AShort: 'A类',
BShort: 'B类',
CShort: 'C类',
},
// 角色
role: {
super: '超级管理员',
manager: '客户经理',
},
// 性别
gender: {
male: '男',
female: '女',
},
// 文件上传
upload: {
text: '点击或拖拽文件到此处添加',
hint: '支持上传不超过50M的文件',
uploaded: '已上传文件',
remove: '删除',
rename: '重命名',
maxSize50M: '(不超过50M)',
},
// 积分页面
points: {
title: '🎁 我的积分',
unit: '分',
rewards: '已获得15次服务奖励',
detail: '积分明细',
points: '积分',
pointsTime: '时间',
pointsSource: '来源',
pointsOrder: '工单号',
pointsChange: '积分变动',
pointsDesc: '说明',
},
// 报告页面
report: {
list: '服务报告列表',
generate: '生成服务报告',
view: '查看',
download: '下载',
remark: '备注',
search: '输入医院名称搜索',
typeAll: '全部类型',
quarterly: '季度报告',
annual: '年度报告',
period: '报告周期',
quarter: '季度',
year: '年度',
querySuccess: '查询完成,找到 {count} 条报告记录。',
},
// 工单详情
orderDetail: {
submitTime: '提交时间',
statusChange: '状态变更日志',
operator: '操作人',
beforeChange: '变更前',
afterChange: '变更后',
noAttachment: '暂无附件',
currentStatus: '当前状态',
dept: '提出科室',
name: '提出人员',
handler: '负责人员',
},
// 修改密码
password: {
title: '修改密码',
oldPassword: '原密码',
newPassword: '新密码',
confirmPassword: '确认密码',
submit: '提交',
cancel: '取消',
success: '密码已修改',
pleaseInputOld: '请输入原密码',
pleaseInputNew: '请输入新密码',
pleaseInputConfirm: '请再次输入新密码',
passwordTooShort: '密码长度至少 6 位',
passwordMismatch: '两次密码不一致',
oldPasswordError: '原密码错误',
accountNotFound: '账号不存在',
},
// 账号管理
account: {
hospitalAccount: '医院账号',
adminAccount: '管理员账号',
list: '账号列表',
addHospital: '+ 添加医院账号',
addAdmin: '+ 添加管理员账号',
enable: '启用',
disable: '禁用',
enableSuccess: '账号 {id} 已启用',
disableSuccess: '账号 {id} 已禁用',
resetPassword: '重置密码',
defaultPassword: '重置后密码将变为默认密码123456',
confirmReset: '确定要重置账号 {id} 的密码吗?',
resetSuccess: '账号 {id} 的密码已重置为默认密码: 123456',
pleaseInputName: '请输入姓名!',
},
// 客户服务
service: {
title: '客户服务',
monthlyView: '📅 月视图',
prevMonth: '← 上月',
nextMonth: '下月 →',
phoneVisit: '📞 电话回访',
onSiteInspection: '🔍 现场巡检',
training: '📚 培训记录',
gift: '🎁 纪念品记录',
expiring: '本月到期提醒',
searchHospital: '按医院名称搜索',
noRecords: '暂无记录',
},
// 通用验证
validation: {
required: '此项必填',
},
// 通用日期范围
dateRange: {
today: '今日',
yesterday: '昨天',
thisWeek: '本周',
thisMonth: '本月',
thisQuarter: '本季度',
},
}
// 公共
common: {
confirm: "确认",
cancel: "取消",
save: "保存",
submit: "提交",
reset: "重置",
query: "查询",
search: "搜索",
add: "添加",
edit: "编辑",
delete: "删除",
view: "查看",
close: "关闭",
back: "返回",
export: "导出",
download: "下载",
upload: "上传",
more: "更多",
all: "全部",
yes: "是",
no: "否",
enabled: "启用",
disabled: "禁用",
pleaseSelect: "请选择",
pleaseInput: "请输入",
success: "成功",
failed: "失败",
operating: "操作",
remark: "备注",
time: "时间",
today: "今日",
yesterday: "昨日",
thisWeek: "本周",
thisMonth: "本月",
thisQuarter: "本季度",
thisYear: "本年",
customDate: "自定义日期",
startDate: "开始日期",
endDate: "结束日期",
language: "语言",
},
// 登录页
login: {
title: "欢迎登录",
name: "康策智能CSM系统",
headerTitle: "康策智能CSM系统",
userName: "请输入账号",
passWord: "请输入密码",
code: "请输入验证码",
jizhu: "记住账号",
denglu: "登 录",
copyright: "上海康策软件有限公司版权所有",
hotline: "服务热线021-60713139",
loginSuccess: "登录成功",
loginFailed: "登录失败",
unknownUserType: "未知用户类型,无法登录",
pleaseEnterUserName: "请输入账号",
pleaseEnterPassWord: "请输入密码",
languageLabel: "语言:",
},
// 导航菜单
nav: {
workbench: "我的工作台",
submit: "我的工单",
points: "我的积分",
quickSubmit: "快速提交",
workorders: "服务工单",
reports: "服务报告",
hospitals: "医院信息",
customer: "客户服务",
managerPoints: "客户经理积分",
account: "账号管理",
grades: "绩效管理",
},
// 页面标题
title: {
workbench: "我的工作台",
submit: "我的工单",
points: "我的积分",
workorders: "服务工单",
reports: "服务报告",
hospitals: "医院信息",
customer: "客户服务",
managerPoints: "客户经理积分",
account: "账号管理",
grades: "绩效管理",
changePassword: "修改密码",
},
// 按钮文本
btn: {
quickSubmit: "快速提交",
view: "查看",
edit: "编辑",
cancel: "取消",
close: "关闭",
detail: "详情",
process: "处理",
submit: "提交工单",
save: "保存修改",
cancelModal: "取消",
saveChange: "保存修改",
query: "查询",
reset: "重置",
export: "导出",
download: "下载",
upload: "上传",
generate: "生成",
add: "添加",
delete: "删除",
addOrder: "+ 新建工单",
addHospital: "+ 添加医院",
addAccount: "+ 添加账号",
quickAddOrder: "+ 快速提交工单",
back: "← 返回",
preview: "查看报告",
downloadPdf: "下载PDF报告",
confirm: "确认修改",
downloadReport: "下载报告",
},
// 表单标签
label: {
title: "问题名称",
description: "问题描述",
attachment: "附件",
dept: "提出科室",
name: "提出人员",
priority: "优先级",
type: "服务类型",
oldPassword: "原密码",
newPassword: "新密码",
confirmPassword: "确认密码",
hospital: "医院名称",
hospitalName: "医院名称",
hospitalSearch: "医院名称",
contact: "联系人",
contactPerson: "联系人",
contactDept: "联系科室",
contactPosition: "职务",
contactPhone: "联系电话",
category: "客户分类",
signDate: "签约时间",
acceptDate: "验收时间",
years: "年限",
maintenanceEndDate: "维保截止时间",
manager: "客户经理",
acceptanceReport: "请上传验收报告",
acceptanceReportTip: "支持上传PDF格式文件必填",
account: "账号",
accountType: "账号类型",
nameAccount: "姓名/账号",
password: "密码",
gender: "性别",
role: "角色",
status: "状态",
renewal: "续保完成",
contractSigned: "合同签署",
paymentPaid: "款项支付",
visited: "回访状态",
visitResult: "回访结果",
createTime: "创建时间",
colorTag: "颜色标签",
currentPassword: "当前密码",
},
// 表单 placeholder
placeholder: {
title: "请输入问题名称",
description: "请详细描述问题,并可以编辑器直接贴图",
dept: "请输入提出科室",
name: "请输入提出人员",
type: "请选择服务类型",
hospital: "请输入医院名称",
contactPerson: "请输入联系人",
contactDept: "请输入联系科室",
contactPosition: "请输入职务",
contactPhone: "请输入联系电话",
search: "请输入",
keyword: "搜索标题/工单号",
account: "请输入账号",
nameOrAccount: "搜索姓名或账号",
password: "请输入密码",
newPassword: "请输入新密码至少6位",
confirmPassword: "请再次输入新密码",
currentPassword: "请输入当前密码",
remark: "请输入备注信息...",
},
// 提示消息
msg: {
pleaseInputTitle: "请输入问题名称",
pleaseInputDescription: "请输入问题描述",
pleaseSelectPriority: "请选择优先级",
pleaseSelectType: "请选择服务类型",
pleaseSelectHospital: "请选择医院",
pleaseInputDept: "请输入提出科室",
pleaseInputName: "请输入提出人员",
passwordTooShort: "新密码至少需要6位",
passwordMismatch: "两次输入的新密码不一致!",
pleaseFillRequired: "请填写必填项!",
submitSuccess: "工单提交成功!",
editSuccess: "工单修改成功!",
cancelSuccess: "工单已成功取消!",
closeSuccess: "工单已成功关闭!",
passwordChangeSuccess: "密码修改成功!",
statusChangeSuccess: "状态切换成功!",
languageChangeSuccess: "语言切换成功!",
themeChangeSuccess: "主题切换成功!",
hospitalAddSuccess: "医院添加成功!",
hospitalEditSuccess: "医院信息修改成功!",
accountAddSuccess: "账号添加成功!",
accountEditSuccess: "账号更新成功!",
passwordResetSuccess: "密码重置成功!",
reportGenerateSuccess: "报告生成成功!",
confirmCancelOrder: "确定要取消工单 {orderId} 吗?取消后将无法恢复。",
confirmCloseOrder: "确定要关闭工单 {orderId} 吗?",
},
// 统计
stat: {
total: "累计提交工单",
completed: "已完成工单",
pending: "待处理工单",
highPriority: "高优先级工单",
totalOrders: "总工单",
pendingOrders: "待处理",
completedOrders: "已完成",
highPriorityOrders: "高优先级",
high: "高优先级",
medium: "中优先级",
low: "低优先级",
mediumPriority: "中优先级",
lowPriority: "低优先级",
processing: "处理中",
},
// 表格列
table: {
id: "工单号",
priority: "优先级",
title: "问题名称",
type: "服务类型",
status: "状态",
time: "提交时间",
submitter: "提交人",
action: "操作",
hospital: "医院名称",
handler: "处理人",
handleTime: "处理时间",
handleDesc: "处理说明",
registrar: "登记人",
dept: "提出科室",
category: "客户分类",
contact: "联系人",
phone: "联系电话",
manager: "客户经理",
signDate: "签约日期",
usageYears: "客户使用年限",
maintenanceEnd: "维保截止时间",
acceptanceReport: "验收报告",
account: "账号",
name: "姓名",
gender: "性别",
role: "角色",
createTime: "创建时间",
hospitalName: "医院名称",
},
// 状态
status: {
pending: "待处理",
processing: "处理中",
completed: "已完成",
closed: "已关闭",
active: "活跃",
inactive: "不活跃",
normal: "正常",
warning: "预警",
urgent: "紧急",
expired: "已过期",
renewed: "已续保",
notRenewed: "未续保",
paid: "已付款",
notPaid: "未付款",
},
// 优先级
priority: {
high: "🔴 高",
medium: "🟠 中",
low: "🟢 低",
},
// 类型
type: {
issue: "故障问题",
consult: "使用咨询",
feature: "功能需求",
other: "其他",
},
// 图表
chart: {
title: "工单趋势",
submit: "提交工单",
complete: "完成工单",
bar: "柱状图",
line: "折线图",
},
// 日期按钮
dateBtn: {
thisMonth: "本月",
thisQuarter: "本季度",
thisYear: "本年",
customDate: "自定义日期",
},
// 主题
theme: {
blue: "穹宇蓝",
purple: "星轨紫",
green: "青峦绿",
title: "更换主题",
},
// 语言
languageSwitch: {
title: "更换语言",
zhCN: "中文简体",
zhTW: "中文繁体",
enUS: "English",
},
// 模态框
modal: {
detail: "工单详情",
edit: "编辑工单",
submit: "快速提交工单",
changePassword: "修改密码",
changeTheme: "更换主题",
changeLanguage: "更换语言",
addAccount: "添加账号",
editAccount: "编辑账号",
resetPassword: "重置密码",
addHospital: "添加医院",
editHospital: "编辑医院",
detailHospital: "医院详情",
generateReport: "生成服务报告",
},
// 用户菜单
userMenu: {
changePassword: "修改密码",
changeTheme: "更换主题",
changeLanguage: "更换语言",
logout: "退出登录",
},
// 客户分类
category: {
A: "A类活跃",
B: "B类不活跃",
C: "C类待挽回",
AShort: "A类",
BShort: "B类",
CShort: "C类",
},
// 角色
role: {
super: "超级管理员",
manager: "客户经理",
},
// 性别
gender: {
male: "男",
female: "女",
},
// 文件上传
upload: {
text: "点击或拖拽文件到此处添加",
hint: "支持上传不超过50M的文件",
uploaded: "已上传文件",
remove: "删除",
rename: "重命名",
maxSize50M: "(不超过50M)",
},
// 积分页面
points: {
title: "🎁 我的积分",
unit: "分",
rewards: "已获得15次服务奖励",
detail: "积分明细",
points: "积分",
pointsTime: "时间",
pointsSource: "来源",
pointsOrder: "工单号",
pointsChange: "积分变动",
pointsDesc: "说明",
},
// 报告页面
report: {
list: "服务报告列表",
generate: "生成服务报告",
view: "查看",
download: "下载",
remark: "备注",
search: "输入医院名称搜索",
typeAll: "全部类型",
quarterly: "季度报告",
annual: "年度报告",
period: "报告周期",
quarter: "季度",
year: "年度",
querySuccess: "查询完成,找到 {count} 条报告记录。",
},
// 工单详情
orderDetail: {
submitTime: "提交时间",
statusChange: "状态变更日志",
operator: "操作人",
beforeChange: "变更前",
afterChange: "变更后",
noAttachment: "暂无附件",
currentStatus: "当前状态",
dept: "提出科室",
name: "提出人员",
handler: "负责人员",
},
// 修改密码
password: {
title: "修改密码",
oldPassword: "原密码",
newPassword: "新密码",
confirmPassword: "确认密码",
submit: "提交",
cancel: "取消",
success: "密码已修改",
pleaseInputOld: "请输入原密码",
pleaseInputNew: "请输入新密码",
pleaseInputConfirm: "请再次输入新密码",
passwordTooShort: "密码长度至少 6 位",
passwordMismatch: "两次密码不一致",
oldPasswordError: "原密码错误",
accountNotFound: "账号不存在",
},
// 账号管理
account: {
hospitalAccount: "医院账号",
adminAccount: "管理员账号",
list: "账号列表",
addHospital: "+ 添加医院账号",
addAdmin: "+ 添加管理员账号",
enable: "启用",
disable: "禁用",
enableSuccess: "账号 {id} 已启用",
disableSuccess: "账号 {id} 已禁用",
resetPassword: "重置密码",
defaultPassword: "重置后密码将变为默认密码123456",
confirmReset: "确定要重置账号 {id} 的密码吗?",
resetSuccess: "账号 {id} 的密码已重置为默认密码: 123456",
pleaseInputName: "请输入姓名!",
},
// 客户服务
service: {
title: "客户服务",
monthlyView: "📅 月视图",
prevMonth: "← 上月",
nextMonth: "下月 →",
phoneVisit: "📞 电话回访",
onSiteInspection: "🔍 现场巡检",
training: "📚 培训记录",
gift: "🎁 纪念品记录",
expiring: "本月到期提醒",
searchHospital: "按医院名称搜索",
noRecords: "暂无记录",
},
// 通用验证
validation: {
required: "此项必填",
},
// 通用日期范围
dateRange: {
today: "今日",
yesterday: "昨天",
thisWeek: "本周",
thisMonth: "本月",
thisQuarter: "本季度",
},
};

@ -133,6 +133,7 @@ export default {
confirmPassword: '確認密碼',
hospital: '醫院名稱',
hospitalName: '醫院名稱',
hospitalSearch: '醫院名稱',
contact: '聯繫人',
contactPerson: '聯繫人',
contactDept: '聯繫科室',
@ -148,6 +149,7 @@ export default {
acceptanceReportTip: '支援上傳PDF格式檔案必填',
account: '帳號',
accountType: '帳號類型',
nameAccount: '姓名/帳號',
password: '密碼',
gender: '性別',
role: '角色',
@ -176,6 +178,7 @@ export default {
search: '請輸入',
keyword: '搜索標題/工單號',
account: '請輸入帳號',
nameOrAccount: '搜索姓名或帳號',
password: '請輸入密碼',
newPassword: '請輸入新密碼至少6位',
confirmPassword: '請再次輸入新密碼',
@ -199,6 +202,7 @@ export default {
cancelSuccess: '工單已成功取消!',
closeSuccess: '工單已成功關閉!',
passwordChangeSuccess: '密碼修改成功!',
statusChangeSuccess: '狀態切換成功!',
languageChangeSuccess: '語言切換成功!',
themeChangeSuccess: '主題切換成功!',
hospitalAddSuccess: '醫院添加成功!',

@ -8,8 +8,8 @@
<el-option label="医院端" value="Hospital" />
</el-select>
</el-form-item>
<el-form-item :label="$t('placeholder.keyword')">
<el-input v-model="filters.keyword" :placeholder="$t('placeholder.keyword')" clearable style="width:200px" />
<el-form-item :label="$t('label.nameAccount')">
<el-input v-model="filters.keyword" :placeholder="$t('placeholder.nameOrAccount')" clearable style="width:200px" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSearch">{{ $t('btn.query') }}</el-button>
@ -118,7 +118,7 @@ const toggleStatus = async (row) => {
row.__loading = true;
try {
await toggleAdminAccountStatus(row.id);
ElMessage.success($t('msg.passwordChangeSuccess'));
ElMessage.success($t('msg.statusChangeSuccess'));
loadList();
} finally {
row.__loading = false;

@ -24,9 +24,9 @@
<el-descriptions-item :label="$t('label.contactPhone')">{{ detail.contactPhone }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.signDate')">{{ formatDate(detail.signDate) }}</el-descriptions-item>
<el-descriptions-item :label="$t('label.acceptDate')">{{ formatDate(detail.acceptDate) }}</el-descriptions-item>
<el-descriptions-item :label="$t('label.years')">{{ detail.contractYears }} {{ $t('common.time') }}</el-descriptions-item>
<el-descriptions-item :label="$t('label.years')">{{ formatUsageYears(detail.signDate) }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.maintenanceEnd')">{{ formatDate(detail.maintenanceEnd) }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.manager')">{{ detail.managerId }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.manager')">{{ detail.managerName }}</el-descriptions-item>
</el-descriptions>
<div class="section">
@ -51,6 +51,18 @@ const detail = ref({});
const formatDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "—");
// 使"XX"
const formatUsageYears = (signDate) => {
if (!signDate) return "—";
const start = dayjs(signDate);
const now = dayjs();
if (start.isAfter(now)) return "—";
const totalDays = now.diff(start, "day");
const years = Math.floor(totalDays / 365);
const days = totalDays - years * 365;
return `${years}${days}`;
};
const loadDetail = async () => {
loading.value = true;
try {

@ -7,7 +7,9 @@
class="page-header"
>
<template #content>
<span class="page-title">{{ isEdit ? $t('modal.editHospital') : $t('modal.addHospital') }}</span>
<span class="page-title">{{
isEdit ? $t("modal.editHospital") : $t("modal.addHospital")
}}</span>
</template>
</el-page-header>
@ -20,7 +22,10 @@
style="max-width: 800px"
>
<el-form-item :label="$t('label.hospitalName')" prop="name">
<el-input v-model="form.name" :placeholder="$t('placeholder.hospital')" />
<el-input
v-model="form.name"
:placeholder="$t('placeholder.hospital')"
/>
</el-form-item>
<el-form-item :label="$t('label.category')" prop="customerCategory">
<el-select
@ -28,9 +33,9 @@
:placeholder="$t('label.category')"
style="width: 200px"
>
<el-option label="A类" value="A" />
<el-option label="B类" value="B" />
<el-option label="C类" value="C" />
<el-option label="A类客户(活跃)" value="A" />
<el-option label="B类客户(不活跃)" value="B" />
<el-option label="C类客户(待挽回)" value="C" />
</el-select>
</el-form-item>
<el-form-item :label="$t('label.contactDept')">
@ -66,7 +71,10 @@
<el-form-item :label="$t('label.years')" prop="contractYears">
<el-input-number v-model="form.contractYears" :min="1" :max="20" />
</el-form-item>
<el-form-item :label="$t('label.maintenanceEndDate')" prop="maintenanceEnd">
<el-form-item
:label="$t('label.maintenanceEndDate')"
prop="maintenanceEnd"
>
<el-date-picker
v-model="form.maintenanceEnd"
type="date"
@ -99,9 +107,11 @@
:on-exceed="handleReportExceed"
accept=".pdf"
>
<el-button type="primary" plain>{{ $t('btn.upload') }}</el-button>
<el-button type="primary" plain>{{ $t("btn.upload") }}</el-button>
<template #tip>
<div class="el-upload__tip">{{ $t('label.acceptanceReportTip') }}</div>
<div class="el-upload__tip">
{{ $t("label.acceptanceReportTip") }}
</div>
</template>
</el-upload>
</el-form-item>
@ -110,9 +120,9 @@
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="submitting" @click="submit">
{{ isEdit ? $t('common.save') : $t('common.add') }}
{{ isEdit ? $t("common.save") : $t("common.add") }}
</el-button>
<el-button @click="goBack">{{ $t('common.cancel') }}</el-button>
<el-button @click="goBack">{{ $t("common.cancel") }}</el-button>
</el-form-item>
</el-form>
</el-card>
@ -157,19 +167,35 @@ const form = reactive({
});
const rules = {
name: [{ required: true, message: () => $t('placeholder.hospital'), trigger: "blur" }],
name: [
{
required: true,
message: () => $t("placeholder.hospital"),
trigger: "blur",
},
],
customerCategory: [
{ required: true, message: () => $t('label.category'), trigger: "change" },
{ required: true, message: () => $t("label.category"), trigger: "change" },
],
signDate: [
{ required: true, message: () => $t("label.signDate"), trigger: "change" },
],
signDate: [{ required: true, message: () => $t('label.signDate'), trigger: "change" }],
acceptDate: [
{ required: true, message: () => $t('label.acceptDate'), trigger: "change" },
{
required: true,
message: () => $t("label.acceptDate"),
trigger: "change",
},
],
contractYears: [
{ required: true, message: () => $t('label.years'), trigger: "blur" },
{ required: true, message: () => $t("label.years"), trigger: "blur" },
],
maintenanceEnd: [
{ required: true, message: () => $t('label.maintenanceEndDate'), trigger: "change" },
{
required: true,
message: () => $t("label.maintenanceEndDate"),
trigger: "change",
},
],
};
@ -187,7 +213,9 @@ const buildHospitalFormData = () => {
if (value === undefined || value === null || value === "") return;
fd.append(key, value);
});
const file = (reportFileList.value || []).map((f) => f.raw).filter(Boolean)[0];
const file = (reportFileList.value || [])
.map((f) => f.raw)
.filter(Boolean)[0];
if (file) fd.append("files", file);
return fd;
};
@ -216,7 +244,7 @@ const submit = async () => {
await formRef.value.validate(async (valid) => {
if (!valid) return;
if (!reportFileList.value?.length) {
ElMessage.warning($t('label.acceptanceReport'));
ElMessage.warning($t("label.acceptanceReport"));
return;
}
submitting.value = true;
@ -224,10 +252,10 @@ const submit = async () => {
const fd = buildHospitalFormData();
if (isEdit.value) {
await updateAdminHospital(route.params.id, fd);
ElMessage.success($t('msg.hospitalEditSuccess'));
ElMessage.success($t("msg.hospitalEditSuccess"));
} else {
await createAdminHospital(fd);
ElMessage.success($t('msg.hospitalAddSuccess'));
ElMessage.success($t("msg.hospitalAddSuccess"));
}
router.replace("/admin/hospitals");
} finally {

@ -2,7 +2,7 @@
<div class="hospital-list">
<el-card shadow="never">
<el-form :inline="true" :model="filters" class="filter-form">
<el-form-item :label="$t('placeholder.keyword')">
<el-form-item :label="$t('label.hospitalSearch')">
<el-input
v-model="filters.keyword"
:placeholder="$t('placeholder.hospital')"
@ -17,9 +17,9 @@
clearable
style="width: 140px"
>
<el-option label="A类" value="A" />
<el-option label="B类" value="B" />
<el-option label="C类" value="C" />
<el-option label="A类客户(活跃)" value="A" />
<el-option label="B类客户(不活跃)" value="B" />
<el-option label="C类客户(待挽回)" value="C" />
</el-select>
</el-form-item>
<el-form-item>
@ -41,7 +41,9 @@
<el-table-column :label="$t('table.contact')" prop="contactPerson" width="100" />
<el-table-column :label="$t('table.phone')" prop="contactPhone" width="140" />
<el-table-column :label="$t('table.manager')" prop="managerName" width="140" />
<el-table-column :label="$t('table.usageYears')" prop="contractYears" width="140" />
<el-table-column :label="$t('table.usageYears')" width="140">
<template #default="{ row }">{{ formatUsageYears(row.signDate) }}</template>
</el-table-column>
<el-table-column :label="$t('table.acceptanceReport')" width="140">
<template #default="{ row }">
<el-button
@ -118,6 +120,18 @@ const filters = reactive({ keyword: "", category: "" });
const formatDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "—");
// 使"XX"
const formatUsageYears = (signDate) => {
if (!signDate) return "—";
const start = dayjs(signDate);
const now = dayjs();
if (start.isAfter(now)) return "—";
const totalDays = now.diff(start, "day");
const years = Math.floor(totalDays / 365);
const days = totalDays - years * 365;
return `${years}${days}`;
};
const loadList = async () => {
loading.value = true;
try {

@ -30,7 +30,7 @@
<el-descriptions-item :label="$t('table.type')">{{ detail.serviceType }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.submitter')">{{ detail.submitter }}</el-descriptions-item>
<el-descriptions-item :label="$t('label.dept')">{{ detail.department }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.time')">{{ detail.createdAt }}</el-descriptions-item>
<el-descriptions-item :label="$t('table.time')">{{ detail.createdAt?.split('T').join(' ') }}</el-descriptions-item>
</el-descriptions>
<div class="section">
@ -42,16 +42,16 @@
<div class="section-title">{{ $t('label.attachment') }} ({{ (detail.attachments || []).length }})</div>
<el-empty v-if="!detail.attachments?.length" :description="$t('orderDetail.noAttachment')" :image-size="80" />
<div v-else class="files">
<el-link
<el-button
v-for="(f, i) in detail.attachments"
:key="i"
:href="getAttachmentUrl(f.fileName)"
target="_blank"
link
type="primary"
class="file-item"
@click="viewReport(f.filePath)"
>
<el-icon><Document /></el-icon>{{ f.fileName }}
</el-link>
</el-button>
</div>
</div>
@ -70,6 +70,21 @@
</el-timeline>
</div>
</el-card>
<el-dialog
v-model="previewVisible"
:title="$t('btn.preview')"
width="80%"
top="5vh"
destroy-on-close
:before-close="closePreview"
>
<iframe
v-if="previewUrl"
:src="previewUrl"
class="preview-iframe"
/>
</el-dialog>
</div>
</template>
@ -77,8 +92,8 @@
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ArrowLeft, Document } from "@element-plus/icons-vue";
import { getAdminOrderDetail } from "@/service/modular/admin";
import { getAttachmentUrl } from "@/service/modular/upload";
import { ElMessage } from "element-plus";
import { getAdminOrderDetail, getUploadFile } from "@/service/modular/admin";
const route = useRoute();
const router = useRouter();
@ -101,6 +116,34 @@ const loadDetail = async () => {
const goBack = () => router.back();
const goProcess = () => router.push(`/admin/orders/process/${route.params.id}`);
const previewVisible = ref(false);
const previewUrl = ref("");
const cleanupPreviewUrl = () => {
if (previewUrl.value) {
URL.revokeObjectURL(previewUrl.value);
previewUrl.value = "";
}
};
const closePreview = () => {
previewVisible.value = false;
cleanupPreviewUrl();
};
const viewReport = async (attachmentPath) => {
if (!attachmentPath) return;
const fileName = String(attachmentPath);
try {
const blob = await getUploadFile(fileName);
cleanupPreviewUrl();
previewUrl.value = URL.createObjectURL(blob);
previewVisible.value = true;
} catch (e) {
ElMessage.error(e?.message || $t('msg.failed'));
}
};
onMounted(loadDetail);
</script>
@ -157,4 +200,9 @@ onMounted(loadDetail);
margin-top: 4px;
}
}
.preview-iframe {
width: 100%;
height: 80vh;
border: 0;
}
</style>

@ -394,7 +394,7 @@ const filters = reactive({
const loadHospitals = async () => {
try {
const res = await getAdminHospitals({ page: 1, pageSize: 1000 });
hospitals.value = res?.list.map || [];
hospitals.value = res?.list || [];
} catch (_) {
hospitals.value = [];
}

Loading…
Cancel
Save