diff --git a/b/product/search_user_inquiry.dspy b/b/product/search_user_inquiry.dspy
index a5ce76d..928e88e 100644
--- a/b/product/search_user_inquiry.dspy
+++ b/b/product/search_user_inquiry.dspy
@@ -55,26 +55,44 @@ async def search_user_inquiry(ns={}):
# 分页查询
search_sql = """select * from product_inquiry where %s order by update_time desc limit %d offset %d;""" % (where_clause, page_size, offset)
result = await sor.sqlExe(search_sql, {})
- dict_sql = """select dict_type, dict_key, dict_value from product_inquiry_dict where status = 1 order by dict_type asc, sort_order asc;"""
+ dict_sql = """
+ select dict_type, dict_key, dict_value_zh, dict_value_en
+ from product_inquiry_dict
+ where status = 1
+ order by dict_type asc, sort_order asc;
+ """
dict_result = await sor.sqlExe(dict_sql, {})
- dict_mapping = {}
+ dict_mapping_zh = {}
+ dict_mapping_en = {}
for dict_item in dict_result:
dict_type = dict_item.get('dict_type')
- dict_mapping.setdefault(dict_type, {})[str(dict_item.get('dict_key'))] = dict_item.get('dict_value')
+ dict_key = str(dict_item.get('dict_key'))
+ dict_mapping_zh.setdefault(dict_type, {})[dict_key] = dict_item.get('dict_value_zh')
+ dict_mapping_en.setdefault(dict_type, {})[dict_key] = dict_item.get('dict_value_en')
- value_mapping = {
+ value_mapping_zh = {
'custom_type': {'0': '个人', '1': '企业'},
- 'enterprise_type': dict_mapping.get('enterprise_type', {}),
- 'region': dict_mapping.get('region', {}),
+ 'enterprise_type': dict_mapping_zh.get('enterprise_type', {}),
+ 'region': dict_mapping_zh.get('region', {}),
'feedback': {'0': '待回复', '1': '已回复'}
}
+ value_mapping_en = {
+ 'custom_type': {'0': 'Individual', '1': 'Enterprise'},
+ 'enterprise_type': dict_mapping_en.get('enterprise_type', {}),
+ 'region': dict_mapping_en.get('region', {}),
+ 'feedback': {'0': 'Pending Reply', '1': 'Replied'}
+ }
for data_dic in result:
- for key, mapping in value_mapping.items():
+ for key in value_mapping_zh.keys():
if key in data_dic:
- data_dic['%s_name' % key] = mapping.get(str(data_dic.get(key)), data_dic.get(key))
- direction_mapping = dict_mapping.get('direction', {})
+ value_key = str(data_dic.get(key))
+ data_dic['%s_name_zh' % key] = value_mapping_zh[key].get(value_key, data_dic.get(key))
+ data_dic['%s_name_en' % key] = value_mapping_en[key].get(value_key, data_dic.get(key))
+ direction_mapping_zh = dict_mapping_zh.get('direction', {})
+ direction_mapping_en = dict_mapping_en.get('direction', {})
direction_keys = str(data_dic.get('consult_direction')).split(',') if data_dic.get('consult_direction') else []
- data_dic['consult_direction_name'] = ','.join([direction_mapping.get(direction_key.strip(), direction_key.strip()) for direction_key in direction_keys if direction_key.strip()])
+ data_dic['consult_direction_name_zh'] = ','.join([direction_mapping_zh.get(direction_key.strip(), direction_key.strip()) for direction_key in direction_keys if direction_key.strip()])
+ data_dic['consult_direction_name_en'] = ', '.join([direction_mapping_en.get(direction_key.strip(), direction_key.strip()) for direction_key in direction_keys if direction_key.strip()])
if ns.get('to_excel') == '1':
# 创建映射字段 导出execl
@@ -106,11 +124,11 @@ async def search_user_inquiry(ns={}):
value = data_dic[key]
chinese_key = field_mapping[key]
if key == 'consult_direction':
- direction_mapping = dict_mapping.get('direction', {})
+ direction_mapping = dict_mapping_zh.get('direction', {})
direction_keys = str(value).split(',') if value else []
new_data_dic[chinese_key] = ','.join([direction_mapping.get(direction_key.strip(), direction_key.strip()) for direction_key in direction_keys if direction_key.strip()])
- elif key in value_mapping:
- mapped_value = value_mapping[key].get(str(value), value) # 若未找到对应映射,保留原始值
+ elif key in value_mapping_zh:
+ mapped_value = value_mapping_zh[key].get(str(value), value) # 若未找到对应映射,保留原始值
new_data_dic[chinese_key] = mapped_value
else:
new_data_dic[chinese_key] = value
diff --git a/b/product/search_user_inquiry_dict.dspy b/b/product/search_user_inquiry_dict.dspy
index c2b770d..7f3ee31 100644
--- a/b/product/search_user_inquiry_dict.dspy
+++ b/b/product/search_user_inquiry_dict.dspy
@@ -4,7 +4,12 @@ async def search_user_inquiry_dict(ns={}):
where_sql = "where status = 1"
if ns.get('dict_type'):
where_sql += " and dict_type = '%s'" % ns.get('dict_type')
- search_sql = """select * from product_inquiry_dict %s order by dict_type asc, sort_order asc;""" % where_sql
+ search_sql = """
+ select id, dict_type, dict_key, dict_value_zh, dict_value_en, sort_order
+ from product_inquiry_dict
+ %s
+ order by dict_type asc, sort_order asc;
+ """ % where_sql
result = await sor.sqlExe(search_sql, {})
return {
'status': True,
diff --git a/docs/superpowers/plans/2026-08-07-bilingual-inquiry-dictionary.md b/docs/superpowers/plans/2026-08-07-bilingual-inquiry-dictionary.md
new file mode 100644
index 0000000..6d258df
--- /dev/null
+++ b/docs/superpowers/plans/2026-08-07-bilingual-inquiry-dictionary.md
@@ -0,0 +1,39 @@
+# Bilingual Inquiry Dictionary Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Adapt inquiry search APIs to the bilingual dictionary value columns.
+
+**Architecture:** Build independent Chinese and English dictionary maps from one query. Return separate language display fields in normal search results while reusing the Chinese map for the existing Excel export.
+
+**Tech Stack:** DSPY Python endpoints, async DBPools/sor access, MySQL.
+
+---
+
+### Task 1: Update inquiry result mapping
+
+**Files:**
+- Modify: `b/product/search_user_inquiry.dspy`
+
+- [ ] Query `dict_value_zh` and `dict_value_en`.
+- [ ] Build separate Chinese and English maps.
+- [ ] Return `*_name_zh` and `*_name_en` for single-choice fields.
+- [ ] Return `consult_direction_name_zh` and `consult_direction_name_en`.
+- [ ] Keep Excel export mapped through Chinese values.
+
+### Task 2: Update dictionary search output
+
+**Files:**
+- Modify: `b/product/search_user_inquiry_dict.dspy`
+
+- [ ] Replace `select *` with the explicit bilingual dictionary columns.
+
+### Task 3: Verify
+
+**Files:**
+- Verify: `b/product/search_user_inquiry.dspy`
+- Verify: `b/product/search_user_inquiry_dict.dspy`
+
+- [ ] Confirm neither SQL query references the removed `dict_value` column.
+- [ ] Compile both DSPY function bodies.
+- [ ] Run IDE diagnostics and `git diff --check`.
diff --git a/docs/superpowers/specs/2026-08-07-bilingual-inquiry-dictionary-design.md b/docs/superpowers/specs/2026-08-07-bilingual-inquiry-dictionary-design.md
new file mode 100644
index 0000000..655c38b
--- /dev/null
+++ b/docs/superpowers/specs/2026-08-07-bilingual-inquiry-dictionary-design.md
@@ -0,0 +1,29 @@
+# 咨询字典双语接口设计
+
+## 目标
+
+咨询相关接口适配 `product_inquiry_dict` 的双语字段
+`dict_value_zh` 和 `dict_value_en`,不再读取旧字段 `dict_value`。
+
+## 接口调整
+
+- `search_user_inquiry.dspy` 同时查询并构建中英文映射。
+- 普通咨询列表分别返回 `*_name_zh` 和 `*_name_en`。
+- 单选字段包括客户类型、企业类型、区域和反馈状态。
+- 多选咨询方向分别返回 `consult_direction_name_zh` 和
+ `consult_direction_name_en`,并保持原选项顺序。
+- Excel 导出继续使用中文表头和中文字典值。
+- `search_user_inquiry_dict.dspy` 明确返回
+ `id`、`dict_type`、`dict_key`、`dict_value_zh`、
+ `dict_value_en`、`sort_order`。
+
+## 兼容边界
+
+旧的 `*_name` 单语字段不再生成。调用方应读取对应的
+`*_name_zh` 或 `*_name_en` 字段。
+
+## 验证
+
+- 字典查询不再引用 `dict_value`。
+- 普通列表中的单选和多选字段均包含中英文显示名称。
+- Excel 仍只输出中文显示值。
diff --git a/f/web-kboss/src/assets/less/news/news.less b/f/web-kboss/src/assets/less/news/news.less
index a70e549..9d7ba55 100644
--- a/f/web-kboss/src/assets/less/news/news.less
+++ b/f/web-kboss/src/assets/less/news/news.less
@@ -2,7 +2,9 @@
position: relative;
min-height: 100vh;
overflow-x: hidden;
+ overflow-y: hidden;
color: #1f2937;
+ padding: 0 12%;
background:
radial-gradient(circle at 78% 18%, rgba(236, 72, 153, 0.07) 0%, rgba(236, 72, 153, 0) 32%),
radial-gradient(circle at 18% 16%, rgba(59, 130, 246, 0.12) 0%, rgba(59, 130, 246, 0) 36%),
@@ -10,10 +12,10 @@
}
.news-shell {
- position: relative;
+ // position: relative;
z-index: 1;
- max-width: 1280px;
- margin: 0 auto;
+ // max-width: 1280px;
+ // margin: 0 auto;
padding: 0 24px;
}
@@ -55,9 +57,9 @@
}
.news-hero {
- position: relative;
+ // position: relative;
padding: 140px 0 72px;
- overflow: hidden;
+ // overflow: hidden;
}
.news-hero::before {
@@ -93,6 +95,8 @@
}
.hero-content {
+ text-align: left;
+ margin: 0 ;
animation: fadeInUp 0.8s ease-out forwards;
}
@@ -197,6 +201,7 @@
.news-item {
position: relative;
overflow: hidden;
+
cursor: pointer;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.04);
diff --git a/f/web-kboss/src/i18n/lang/en-US.js b/f/web-kboss/src/i18n/lang/en-US.js
index 3514dc2..823fd09 100644
--- a/f/web-kboss/src/i18n/lang/en-US.js
+++ b/f/web-kboss/src/i18n/lang/en-US.js
@@ -401,5 +401,59 @@ export default {
openedDecision: 'The Investment Strategy Agent page has been opened.
Anything else you would like to know?',
openedPage: 'The related page has been opened. Anything else you would like to know?'
},
+ loginDialog: {
+ welcomeLogin: 'Welcome',
+ createAccount: 'Create Account',
+ signIn: 'Sign In',
+ signUp: 'Sign Up',
+ signInWithPassword: 'Password',
+ signInWithCode: 'Verification Code',
+ enterAccount: 'Enter account',
+ enterPassword: 'Enter password',
+ enterMobile: 'Enter mobile number',
+ enterVerificationCode: 'Enter verification code',
+ enterAccountName: 'Enter account name',
+ forgotPassword: 'Forgot password?',
+ noAccountSignUp: 'No account? Sign Up',
+ signInNow: 'Sign In',
+ getVerificationCode: 'Get Verification Code',
+ agreePrefix: 'I have read and agree to the ',
+ userAgreement: 'User Agreement',
+ agreeAnd: ' and ',
+ privacyPolicy: 'Privacy Policy',
+ signUpNow: 'Sign Up',
+ hasAccountSignIn: 'Already have an account? Sign In',
+ signingIn: 'Signing in...',
+ signingUp: 'Signing up...',
+ resendCode: 'Resend {seconds}s',
+ mobileRequired: 'Enter mobile number',
+ mobileInvalid: 'Please enter a valid mobile number',
+ accountRequired: 'Enter account',
+ passwordRequired: 'Enter password',
+ codeRequired: 'Enter verification code',
+ accountNameRequired: 'Enter account name',
+ agreeRequired: 'Please read and agree to the agreements first',
+ codeSent: 'Verification code sent',
+ codeSendFail: 'Failed to get verification code',
+ loginFail: 'Sign in failed',
+ loginSuccess: 'Signed in successfully',
+ registerSuccess: 'Registration successful. Please sign in.',
+ registerFail: 'Registration failed',
+ registerRetry: 'Registration failed. Please try again.',
+ resetPassword: 'Reset Password',
+ resetPasswordDesc: 'Verify identity via mobile verification code to set a new password',
+ mobileLabel: 'Mobile Number',
+ newPasswordLabel: 'New Password',
+ verificationCodeLabel: 'Verification Code',
+ enterBoundMobile: 'Enter bound mobile number',
+ enterNewPassword: 'Enter new password',
+ cancel: 'Cancel',
+ confirmReset: 'Confirm Reset',
+ newPasswordRequired: 'Enter new password',
+ getCodeFirst: 'Please get the verification code first',
+ resetSuccess: 'Password reset successfully',
+ resetFail: 'Password reset failed',
+ codeSentCheck: 'Verification code sent. Please check your messages.'
+ },
...autoMessages
}
diff --git a/f/web-kboss/src/i18n/lang/zh-CN.js b/f/web-kboss/src/i18n/lang/zh-CN.js
index 09ec8bd..4925636 100644
--- a/f/web-kboss/src/i18n/lang/zh-CN.js
+++ b/f/web-kboss/src/i18n/lang/zh-CN.js
@@ -401,5 +401,59 @@ export default {
openedDecision: '已为您打开投策智能体页面 📊
还有其他想了解的吗?',
openedPage: '已为您打开相关页面。还有其他想了解的吗?'
},
+ loginDialog: {
+ welcomeLogin: '欢迎登录',
+ createAccount: '创建账号',
+ signIn: '登录',
+ signUp: '注册',
+ signInWithPassword: '密码登录',
+ signInWithCode: '验证码登录',
+ enterAccount: '请输入账户',
+ enterPassword: '请输入密码',
+ enterMobile: '请输入手机号',
+ enterVerificationCode: '请输入验证码',
+ enterAccountName: '请输入账户名',
+ forgotPassword: '忘记密码?',
+ noAccountSignUp: '没有账号?去注册',
+ signInNow: '立即登录',
+ getVerificationCode: '获取验证码',
+ agreePrefix: '我已阅读并同意',
+ userAgreement: '《用户协议》',
+ agreeAnd: '、',
+ privacyPolicy: '《隐私政策》',
+ signUpNow: '立即注册',
+ hasAccountSignIn: '已有账号?前往登录',
+ signingIn: '登录中...',
+ signingUp: '注册中...',
+ resendCode: '重新发送 {seconds}s',
+ mobileRequired: '请输入手机号',
+ mobileInvalid: '请输入正确的手机号',
+ accountRequired: '请输入账户',
+ passwordRequired: '请输入密码',
+ codeRequired: '请输入验证码',
+ accountNameRequired: '请输入账户名',
+ agreeRequired: '请先阅读并同意相关协议',
+ codeSent: '验证码已发送',
+ codeSendFail: '验证码获取失败',
+ loginFail: '登录失败',
+ loginSuccess: '登录成功',
+ registerSuccess: '注册成功,请登录',
+ registerFail: '注册失败',
+ registerRetry: '注册失败,请重试',
+ resetPassword: '重置密码',
+ resetPasswordDesc: '通过手机号验证码验证身份后设置新密码',
+ mobileLabel: '手机号',
+ newPasswordLabel: '新密码',
+ verificationCodeLabel: '验证码',
+ enterBoundMobile: '请输入绑定手机号',
+ enterNewPassword: '请输入新密码',
+ cancel: '取消',
+ confirmReset: '确认重置',
+ newPasswordRequired: '请输入新密码',
+ getCodeFirst: '请先获取验证码',
+ resetSuccess: '密码重置成功',
+ resetFail: '密码重置失败',
+ codeSentCheck: '验证码已发送,请注意查收。'
+ },
...autoMessages
}
diff --git a/f/web-kboss/src/views/LoginDialog/LoginDialog.vue b/f/web-kboss/src/views/LoginDialog/LoginDialog.vue
index ec5920c..707e64e 100644
--- a/f/web-kboss/src/views/LoginDialog/LoginDialog.vue
+++ b/f/web-kboss/src/views/LoginDialog/LoginDialog.vue
@@ -13,31 +13,31 @@