main #153

Merged
charles merged 13 commits from main into prod 2026-08-05 10:35:03 +08:00
24 changed files with 3652 additions and 2133 deletions

View File

@ -170,7 +170,11 @@ async def sync_model_to_llm(ns={}):
async def upsert_llm(sor, item):
llm_data = build_llm_data(item)
exist_llm = await sor.R('llm', {'model': item.get('model')})
# 厂商 id 是 llm 表主键,优先按 id 更新,避免模型名称变化后重复插入主键
exist_llm = await sor.R('llm', {'id': llm_data.get('id')})
if not exist_llm:
# 兼容历史数据:相同 model 可能已使用其他本地主键
exist_llm = await sor.R('llm', {'model': item.get('model')})
if exist_llm:
llm_data['id'] = exist_llm[0].get('id')
await sor.U('llm', llm_data)

View File

@ -4,7 +4,7 @@ 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 id, dict_type, dict_key, dict_value, sort_order from product_inquiry_dict %s order by dict_type asc, sort_order asc;""" % where_sql
search_sql = """select * from product_inquiry_dict %s order by dict_type asc, sort_order asc;""" % where_sql
result = await sor.sqlExe(search_sql, {})
return {
'status': True,

View File

@ -66,7 +66,9 @@ async def get_ipc_logo(ns={}):
"home": {
"logoImg": "https://www.opencomputing.cn/idfile?path=logo_ncmatch.png",
"bannerTitle": "开元数智",
"adress": "北京市石景山区和平西路60号院1号楼11层1101-30",
"address": "北京市石景山区和平西路60号院1号楼11层1101-30",
"address_zh": "北京市石景山区和平西路60号院1号楼11层1101-30",
"address_en": "Room 1101-30, 11th Floor, Building 1, No. 60 Heping West Road, Shijingshan District, Beijing",
"footerTitle": "开元数智(北京)科技有限公司",
'qrCode': 'https://www.opencomputing.cn/idfile?path=firstpagehot/ncmatch_inquiry.jpg',
'footer_info': '京ICP备2022001945号-4 开元数智(北京)科技有限公司',
@ -97,7 +99,9 @@ async def get_ipc_logo(ns={}):
"home": {
"logoImg": "https://zgcopc.opencomputing.cn/idfile?path=logo_zgcopc.png",
"bannerTitle": "中关村国际孵化器",
"adress": "北京市海淀区上地信息路2号",
"address": "北京市海淀区上地信息路2号",
"address_zh": "北京市海淀区上地信息路2号",
"address_en": "Building 2, No. 2 Xindao Road, Shangdi, Haidian District, Beijing",
"footerTitle": "中关村国际孵化器有限公司",
'qrCode': 'https://zgcopc.opencomputing.cn/idfile?path=firstpagehot/ncmatch_inquiry.jpg',
'footer_info': '京ICP备13007859号-1 北京中关村国际孵化器有限公司',
@ -127,7 +131,9 @@ async def get_ipc_logo(ns={}):
"home": {
"logoImg": "https://www.opencomputing.cn/idfile?path=logo.png",
"bannerTitle": "开元云",
"adress": "北京市朝阳区东三环中路65号富力中心",
"address": "北京市朝阳区东三环中路65号富力中心",
"address_zh": "北京市朝阳区东三环中路65号富力中心",
"address_en": "R&F Center, 65 East 3rd Ring Middle Rd, Chaoyang, Beijing",
"footerTitle": "开元云(北京)科技有限公司",
'qrCode': 'https://www.opencomputing.cn/idfile?path=firstpagehot/kaiyuancloud_inquiry.png',
'footer_info': '京公网安备11010502054007号 开元云(北京)科技有限公司',

View File

@ -0,0 +1,26 @@
import json
from pathlib import Path
root = Path(__file__).resolve().parents[1]
paras = json.loads((root / 'tmp_user_agreement.json').read_text(encoding='utf-8'))
existing = (root / 'src/views/homePage/agreement/agreementDocs.js').read_text(encoding='utf-8')
privacy_start = existing.index(" 'privacy': {")
privacy_block = existing[privacy_start:]
lines = [
'export default {',
" 'user': {",
" 'title': '用户协议',",
" 'paragraphs': ["
]
for p in paras:
esc = p.replace('\\', '\\\\').replace("'", "\\'")
lines.append(f" '{esc}',")
lines[-1] = lines[-1].rstrip(',')
lines.append(' ]')
lines.append(' },')
lines.append(privacy_block)
out = root / 'src/views/homePage/agreement/agreementDocs.js'
out.write_text('\n'.join(lines), encoding='utf-8')
print(f'Updated {out} with {len(paras)} paragraphs')

View File

@ -0,0 +1,178 @@
# -*- coding: utf-8 -*-
from pathlib import Path
USER_PARAGRAPHS = [
'<strong>开元云用户协议</strong>',
'更新日期【2026】年【7】月【30】日',
'生效日期【2026】年【7】月【30】日',
'本《开元云用户协议》(以下简称“本协议”)由开元云(北京)科技有限公司(以下简称“开元云”或“我们”)与注册、访问或使用开元云服务的自然人、法人或非法人组织(以下简称“用户”或“您”)订立。',
'<strong>请您在注册、下单或使用服务前完整阅读本协议。与责任限制、费用、服务暂停或终止、数据处理及争议解决有关的条款已采用加粗方式提示。您点击同意、提交订单、开通或实际使用服务,均表示您已阅读并同意本协议。您代表法人或其他组织操作的,应保证已取得充分授权。</strong>',
'<strong>1. 协议范围与定义</strong>',
'1.1. 开元云平台,是指由开元云运营的网站、业务平台、客户端、控制台、应用程序、接口及其他服务载体,包括开元算力应用服务平台及后续更名、升级或新增的服务载体。',
'1.2. 开元云服务,是指开元云通过平台或双方确认的订单提供的云计算、算力、算力网络、人工智能及相关产品和技术服务,具体以产品页面、订单或服务说明为准。',
'1.3. 开元云既可能直接提供服务,也可能代理销售、转售或协助交付第三方服务。实际销售方、服务提供方、开票方及售后责任方,以订单记载为准。',
'1.4. 订单,是指用户通过平台提交并由系统确认的订单,以及双方签署或确认的报价单、采购单、服务单、工作说明书或其他交易文件。订单应列明或能够确定服务内容、服务期限、计费方式、实际销售方或服务提供方、开票方、售后责任方及适用的服务规则。',
'1.5. 本协议与订单、产品说明、服务等级协议、隐私政策及适用的平台规则共同构成双方协议。约定不一致时,按双方专项书面约定、订单、产品专项规则、本协议的顺序适用;法律另有规定的除外。',
'<strong>2. 账户注册与管理</strong>',
'2.1. 您应按要求提供真实、准确、完整、有效的注册及认证信息,并在信息变化后及时更新。特定服务依法需要实名核验、资质审查或安全评估的,您应予配合。',
'2.2. 您应妥善保管账户及认证信息,并合理设置操作权限。通过您账户实施的操作原则上视为您的行为,但您能够证明账户被未经授权使用且已及时采取合理措施的除外。',
'2.3. 发现账户或认证信息被盗用、泄露或存在异常操作时,您应及时通知开元云并采取必要措施。开元云可根据风险采取身份复核、限制登录或临时冻结等措施。',
'2.4. 未经开元云同意,您不得转让、出租、出借账户,或者以共享账户等方式规避计费、资质审查或访问控制。',
'<strong>3. 服务订购与交付</strong>',
'3.1. 服务内容、期限、费用、交付方式、技术指标及支持标准,以产品页面、订单或双方书面约定为准。您应在下单前核对相关信息。',
'3.2. 平台展示内容符合要约条件且订单提交成功的,订单成立;订单明确需经资源、资质或合规审核的,以开元云确认、服务开通或双方签署书面文件时成立。',
'3.3. 对开元云直接提供的服务,开元云按约承担交付、维护及售后责任。对第三方服务,各方责任依订单及订购前向您提供的第三方规则确定。<strong>开元云的代理或平台角色不免除其依法应承担的信息披露、平台管理及因自身过错产生的责任。</strong>',
'3.4. 服务可通过账户开通、资源交付、接口启用、部署完成或订单约定的方式交付。需要验收的,按订单约定办理;订单未约定验收期限的,您应在收到交付通知后五个工作日内完成合理核验并反馈问题,隐蔽缺陷不受该期限限制。',
'3.5. 服务变更、扩容、迁移或定制开发,应通过订单、变更单或双方书面确认实施。',
'<strong>4. 订购、交付与验收</strong>',
'4.1. 您应在下单前核对服务名称、配置、数量、价格、第三方服务商及限制等条件。平台提供订单更正和取消入口的,您可在订单确认前修改;订单确认后的变更、退订或迁移按对应产品规则或双方约定办理。',
'4.2. 平台展示的信息符合要约条件且用户提交订单成功的,订单成立;平台明确为要约邀请,或订单需经资源、资质、信用或合规审核的,以开元云确认、资源开通或双方签署书面文件时成立。开元云不得以格式条款约定用户付款后合同仍不成立。',
'4.3. 服务通过账户开通、资源交付、许可码发送、接口启用、部署完成或订单约定的其他方式交付。需要验收的,验收标准和期限以订单为准;订单未约定的,用户应在收到交付通知后五个工作日内完成合理核验并反馈可复现的问题,不影响用户依法就隐蔽缺陷主张权利。',
'4.4. 按周期续费的服务,以订单是否设置自动续费为准。开元云在自动扣款前应以合理方式提示扣款金额和时间,并提供便捷的取消方式;用户取消后不再产生下一周期费用,但已生效周期按约定继续履行。',
'4.5. 资源扩容、迁移、版本升级、服务内容变更或定制开发,应通过新订单、变更单或双方书面确认实施。未经确认的口头沟通不构成对服务范围、费用或期限的变更。',
'<strong>5. 费用、支付、发票与退款</strong>',
'<strong>5.1. 您应按照订单约定的价格、计费单位、结算周期和支付期限付款。因用户使用量、配置或调用次数变化产生的费用,以平台计量记录和订单计费规则为准;用户对计量结果有异议的,应在账单出具后十五日内提出,开元云应提供合理的核验渠道。</strong>',
'5.2. 除订单另有约定,价格不含因用户自身支付方式产生的银行手续费或其他第三方费用。开元云调整服务价格的,应在调整生效前通过平台公告、站内信、电子邮件或订单页面通知;已生效的固定期限订单不受影响,按量服务和续费周期自通知载明的日期适用新价格。',
'5.3. 发票由订单或结算页面列明的开票主体依法开具。您应提供真实、准确的开票信息;因信息错误造成的重开、红冲或邮寄成本,由责任方承担。',
'<strong>5.4. 退订、退款及未消费余额的处理,以订单和对应产品规则为准。涉及第三方服务的,还受第三方服务商的退订条件和资源采购规则约束。</strong>',
'5.5. 用户逾期付款的,开元云可催告并给予合理补救期限;用户在期限届满后仍未付款的,开元云可暂停相应服务并按订单约定收取违约金。暂停前,开元云应在合理可行范围内提示用户备份或迁移数据;紧急安全风险、恶意欠费或法律要求立即暂停的除外。',
'<strong>6. 用户数据与个人信息</strong>',
'6.1. 用户对其通过服务上传、生成、存储或处理的数据和内容(以下简称“用户数据”)依法享有相应权利。除履行协议、维护安全、遵守法律或取得用户授权外,开元云不取得用户数据的所有权,也不将其用于与提供服务无关的目的。',
'6.2. 开元云为账户管理、交易结算、客户服务、安全保障及依法运营而处理个人信息的,按照《开元云隐私政策》执行。',
'6.3. 用户决定个人信息处理目的和方式、开元云仅按用户指示提供处理能力的,用户应保证具有合法处理依据;开元云应按照约定和用户的合法指示处理,并采取与风险相适应的安全措施。必要时,双方可另行签署数据处理协议。',
'<strong>6.4. 为履行订单确需委托第三方处理或向第三方提供用户数据的,开元云应依法履行告知、合同约束及安全管理义务。未经合法依据,不得向无关第三方提供用户个人信息。</strong>',
'6.5. 涉及数据跨境的,由依法负有责任的一方完成相应合规程序。开元云不得在未告知用户的情况下擅自改变订单约定的数据存储地域。',
'6.6. 开元云应采取必要的网络和数据安全措施。发生可能影响用户权益的安全事件时,应及时采取补救措施,并按法律规定和合同约定履行通知、报告义务。',
'6.7. 服务终止后,开元云按照订单、产品规则或数据处理协议提供合理的数据导出期限,并在期限届满后依法删除或匿名化处理用户数据;依法需要留存的除外。',
'<strong>7. 知识产权</strong>',
'7.1. 开元云平台、软件、接口、文档、商标及相关技术成果的知识产权归开元云或相应权利人所有。未经许可,用户不得超出订单及产品规则约定的范围使用。',
'7.2. 服务期限内,用户获得仅限自身合法业务使用的、非独占且不可转让的使用权。第三方产品或开源组件适用其各自许可条款。',
'7.3. 用户数据及用户自行开发成果的权利,依法或依双方约定确定。用户授权开元云在提供和保障服务所必需的范围内处理用户数据。<strong>未经用户另行明确授权,开元云不得使用用户的非公开业务数据训练面向不特定用户的通用模型。</strong>',
'7.4. 人工智能或模型服务的输出可能存在不准确或权利瑕疵。用户应结合使用场景进行核验,并依法处理输出内容的使用及权利风险。',
'<strong>8. 服务运行与变更</strong>',
'8.1. 开元云按照订单或服务等级协议维护其直接提供的服务。第三方服务的可用性、维护及补偿标准,以订单和第三方规则为准;开元云作出更高承诺的,从其承诺。',
'8.2. 因维护升级需要计划中断服务的,开元云应按约提前通知;遇有安全事件、重大故障或主管机关要求等紧急情况,可先行处置并及时通知。',
'8.3. 开元云可以对服务进行合理升级或调整。涉及主要功能、关键技术指标、数据处理方式或费用的重大变化,应提前合理通知;变化实质影响合同目的的,用户可依法解除受影响的服务。',
'8.4. 第三方停止或变更服务导致迁移、替换或退订的,开元云应及时通知并提供合理处理方案。费用和责任按照订单、第三方规则及各方过错确定。',
'<strong>9. 服务暂停与终止</strong>',
'9.1. 用户可按订单和产品规则申请退订或停止续费。固定期限服务到期且未续费的,服务终止。',
'<strong>9.2. 用户逾期付款、严重违反本协议、造成现实安全风险,或者依法需要暂停服务的,开元云可根据风险限制或暂停相关服务。除紧急情形外,开元云应事先通知并给予合理补救期限。</strong>',
'9.3. 一方严重违约且在合理期限内未改正的,守约方可解除受影响的订单;违约无法补救或导致重大安全风险的,可立即解除。',
'9.4. 服务终止不影响终止前已经产生的付款、保密、数据处理、责任承担及争议解决义务。用户数据按照第6.7条处理。',
'<strong>10. 保证、免责与责任限制</strong>',
'10.1. 开元云应以符合行业合理标准的技术和管理措施提供服务。除订单、产品说明或法律另有规定外,开元云不保证服务适合用户的特定目的或实现特定结果。',
'<strong>10.2. 人工智能、模型、智能分析及计算结果可能存在错误、遗漏或偏差,仅供辅助使用,不能替代专业审查、验证或依法应由人工作出的决定。本条不免除开元云因虚假宣传、违反明示承诺或自身过错依法应承担的责任。</strong>',
'10.3. 因用户自身原因或不属于开元云控制范围的第三方原因造成的损失,由责任方依法承担;开元云对其自身过错承担相应责任。',
'<strong>10.4. 在法律允许的范围内,一方仅对其违约或过错造成的直接且可合理预见的损失承担责任。除法律规定不得限制的责任以及开元云故意、重大过失外,开元云就单一订单承担的累计赔偿责任,以索赔事件发生前十二个月内用户就该订单项下受影响服务实际支付的费用总额为上限;订单另有约定的,从其约定。</strong>',
'10.5. 本协议的免责或限责条款不适用于法律禁止免责或限制责任的情形,也不影响消费者依法享有的权利。',
'<strong>11. 保密</strong>',
'11.1. 一方因订立或履行本协议知悉的对方非公开技术、经营、数据及其他依其性质应属保密的信息,均为保密信息。接收方仅可为履行本协议使用,并应采取合理保护措施。',
'11.2. 已经合法公开、从无保密义务的第三方合法取得、接收方能够证明独立取得,或披露方同意公开的信息,不受前款限制。依法应披露的,接收方可在法定范围内披露,并在法律允许时通知披露方。',
'11.3. 保密义务在协议终止后持续五年;商业秘密、个人信息及重要数据依法律规定持续保护。',
'<strong>12. 不可抗力与通知</strong>',
'12.1. 因不能预见、不能避免且不能克服的事件导致不能履行的,受影响方在法律允许范围内部分或全部免责,但迟延履行后发生不可抗力的除外。受影响方应及时通知并采取合理减损措施。',
'12.2. 不可抗力持续超过六十日且导致合同目的不能实现的,任一方可解除受影响的未履行部分,已实际履行的服务按履行情况结算。',
'12.3. 开元云可通过平台公告、站内信、账户通知、电子邮件、短信或订单约定的方式发送通知。涉及费用、主要功能、数据处理、服务暂停终止或争议解决的重大事项,应以能够合理到达用户的显著方式通知。',
'12.4. 您应及时维护有效联系方式。因您未及时更新导致通知无法送达的,由您承担相应后果;开元云明知联系方式失效仍向该地址发送的除外。',
'<strong>12.5. 开元云可因法律变化、服务调整或安全需要修改本协议。对用户权利义务有重大影响的修改,应在生效前显著通知。用户不同意的,可在生效前停止使用并按适用规则终止未履行服务。法律另有规定的,从其规定。</strong>',
'<strong>13. 法律适用与其他</strong>',
'13.1. 本协议的订立、效力、解释、履行及争议解决适用中华人民共和国大陆地区法律。',
'13.2. 双方应先协商解决争议。协商不成的,任一方可向开元云住所地有管辖权的人民法院提起诉讼;消费者依法有权选择其他有管辖权法院的,从其规定。',
'13.3. 双方是独立合同主体。本协议不成立合伙、合资、劳动或未经明确授权的代理关系。',
'13.4. 一方未行使或迟延行使权利,不构成放弃。部分条款无效或不可执行的,不影响其他条款的效力。',
'13.5. 本协议以电子形式订立,与纸质协议具有同等法律效力。用户可通过平台或客服获取、保存和下载协议文本及交易记录。',
'13.6. 客服联系方式【400-6150805 010-65917875】电子邮箱【Open-computing@kaiyuancloud.cn】。联系方式变更的以开元云平台依法公示的信息为准。',
]
PRIVACY_PARAGRAPHS = [
'<strong>开元云隐私政策</strong>',
'版本更新日期【2026年7月30日】',
'版本生效日期【2026年7月30日】',
'开元云(北京)科技有限公司(以下简称“开元云”或“我们”)重视您的个人信息和隐私保护。本政策适用于我们通过开元云官方网站、开放算力应用服务平台及其他由我们运营并明确适用本政策的产品和服务(统称“开元云服务”)处理个人信息的活动。某项服务另有专门隐私规则的,专门规则优先适用;未约定的事项,适用本政策。',
'开元云服务涉及算力服务、算力网络、AI应用、云平台和相关技术服务。您代表单位使用服务的请确认已取得必要授权您向我们提供他人个人信息的应当确保来源合法并已依法履行告知、取得同意等义务。',
'请您在使用开元云服务前阅读本政策。涉及敏感个人信息、向其他个人信息处理者提供个人信息或向境外提供个人信息等依法需要单独同意的事项,我们将另行告知并依法取得您的单独同意。',
'<strong>一、定义</strong>',
'1. 个人信息:以电子或者其他方式记录的、与已识别或者可识别的自然人有关的各种信息,不包括匿名化处理后的信息。',
'2. 敏感个人信息:一旦泄露或者被非法使用,容易导致自然人的人格尊严受到侵害或者人身、财产安全受到危害的个人信息。开元云仅在特定目的、充分必要并采取严格保护措施的情况下处理敏感个人信息。',
'3. 匿名化:个人信息经过处理无法识别特定自然人且不能复原的过程。',
'4. 用户业务数据:用户在使用开元云服务过程中上传、生成、存储、传输或委托开元云处理的数据,不当然属于个人信息;其中含有个人信息的部分,依照适用法律和双方约定处理。',
'<strong>二、我们如何收集和使用个人信息</strong>',
'我们遵循合法、正当、必要和诚信原则,仅为明确、合理且与服务直接相关的目的处理个人信息。具体功能所需信息以实际页面、订单、合同或单独告知为准,主要包括:',
'1. 账号和联系信息。当您注册、登录或管理账号时,我们可能处理您的账号名称、手机号码、电子邮箱、密码密文及账号安全设置,用于创建账号、身份验证、发送必要通知和保障账号安全。拒绝提供必要信息可能导致无法使用账号功能,但通常不影响浏览公开内容。',
'2. 企业认证和交易信息。当您申请试用、购买算力或其他服务、签订或履行合同、结算或开具发票时,我们可能处理单位名称、统一社会信用代码、联系人及联系方式、服务配置、订单、合同、支付状态和开票信息,用于确认交易主体、交付服务、结算、售后和财务管理。支付机构直接处理的银行卡等信息由其依照自身规则处理,我们原则上仅接收完成交易所需的支付结果。',
'3. 咨询和服务记录。当您提交咨询、工单、投诉或参加业务活动时,我们可能处理您提交的姓名、联系方式、单位、需求描述、沟通记录和附件,用于回复请求、排查问题和改进服务。非提供服务所必需的调研或推广信息,我们将在必要时另行取得同意,并提供便捷的退订方式。',
'4. 设备、日志和安全信息。您访问或使用开元云服务时我们可能自动记录IP地址、浏览器和设备类型、访问时间、操作记录、故障日志及安全日志用于运行服务、定位故障、统计基本使用情况和防范网络攻击、欺诈或其他安全风险。我们不会仅因设备或日志信息而不合理限制您的服务。',
'5. 依法需要核验的信息。如特定产品、交易或监管要求确需进行个人或企业身份核验,我们可能处理姓名、身份证明或主体资质等必要信息,并在收集前另行说明具体目的、方式、范围和保存期限。涉及敏感个人信息的,我们将采取更严格的保护措施并依法取得单独同意;如有非敏感的替代核验方式,我们将按实际情况提供。',
'我们依据您的同意、订立或履行合同所必需、履行法定义务,或者法律规定的其他基础处理个人信息。处理目的、方式或个人信息种类发生变化的,我们将依法重新告知,并在需要时重新取得同意。除法律另有规定外,您可以撤回基于同意作出的授权;撤回不影响撤回前处理活动的效力。',
'<strong>三、Cookie和同类技术</strong>',
'1. 为保障网站正常运行、保持登录状态、保存必要设置、分析故障和防范安全风险我们可能使用Cookie和同类技术。必要Cookie被禁用后部分功能可能无法正常使用对于非必要Cookie我们将依法提供选择或关闭方式。',
'2. 您可以通过浏览器设置管理或删除Cookie。清除或拒绝Cookie可能使您需要重新登录或设置偏好但不影响与相关Cookie无关的服务。我们不会将Cookie用于本政策未说明的目的。',
'<strong>四、用户业务数据</strong>',
'1. 您或您的单位在使用算力、存储、网络、模型、智能文档处理或其他开元云服务时上传、生成、存储、传输或委托我们处理的数据,属于用户业务数据。其中含有个人信息的,您或您的单位通常决定处理目的和方式,我们按照双方协议和您的合法指示提供受托处理服务。',
'2. 您应当确保业务数据来源、内容及处理活动合法,并根据适用法律向相关个人履行告知、取得同意等义务。除非产品说明、订单或合同另有明确约定并具备合法处理基础,或者法律另有规定,我们不会将用户业务数据用于自身营销、训练通用模型或其他与提供约定服务无关的目的。',
'用户业务数据与我们为账号管理、交易结算、客户支持和安全保障而独立处理的信息,适用不同的责任分工。具体数据位置、备份、迁移、删除和安全要求,以对应产品说明、订单或合同为准。',
'<strong>五、委托处理、对外提供、转让和公开披露</strong>',
'1. 为提供和保障开元云服务,我们可能委托基础设施、算力、网络、模型接口、身份核验、支付结算、电子签约、发票、客服或安全服务提供方处理必要的个人信息。我们将根据服务性质选择合作方,通过合同约定处理目的、期限、方式、信息种类、安全措施和双方责任,并进行必要监督。合作方不得将受托信息用于自身目的。',
'2. 如需向其他个人信息处理者提供您的个人信息,我们将依法告知接收方信息、处理目的、方式和个人信息种类,并在法律要求时取得您的单独同意。涉及敏感个人信息的,我们还会说明必要性及对个人权益的影响。我们不会出售个人信息。',
'3. 发生合并、分立、重组、资产转让或类似交易而需要转移个人信息的,我们将向您告知接收方信息,并要求接收方继续履行本政策和法律规定的义务;接收方变更原处理目的或方式的,应当依法重新取得同意。',
'4. 我们原则上不公开披露个人信息。确需公开披露的,将告知披露目的、方式和信息种类,依法取得单独同意并采取相应保护措施,法律另有规定的除外。',
'<strong>六、个人信息的保存和安全保护</strong>',
'1. 我们按照实现处理目的所必要的最短时间保存个人信息;法律法规、监管规定或双方合同另有要求的,从其规定。保存期限届满后,我们将删除个人信息或进行匿名化处理;因技术原因暂时无法删除的,将停止除存储和采取必要安全保护措施之外的处理。',
'2. 我们在中华人民共和国境内收集和产生的个人信息原则上存储在境内。具体产品的数据中心和用户业务数据存储位置以产品说明、订单或合同为准。',
'3. 我们根据个人信息的种类、处理目的和风险采取与之相适应的安全措施,包括权限控制、身份认证、传输和存储保护、日志审计、备份恢复、人员管理及安全事件处置。互联网环境并非绝对安全,请您妥善保管账号和认证凭证,不要通过不安全渠道发送敏感信息。',
'4. 发生或者可能发生个人信息泄露、篡改、丢失时,我们将立即采取补救措施,并依照法律规定向主管部门报告;可能对您的权益造成危害的,我们将依法告知事件情况、可能影响、已采取或拟采取的措施及降低风险的建议。',
'<strong>七、您的权利</strong>',
'1. 在法律规定范围内,您有权知情、决定、限制或拒绝我们处理您的个人信息,并可请求查阅、复制、更正、补充或删除个人信息,撤回同意、注销账号,以及要求我们解释个人信息处理规则。我们利用个人信息进行自动化决策并对您的权益产生重大影响的,您有权要求说明,并有权拒绝仅通过自动化决策作出的决定。',
'2. 您可以通过产品提供的账号设置、工单或本政策所列联系方式提出请求。为保护账号和信息安全,我们可能验证您的身份,并在法律规定的期限内处理。请求明显不合理、超出必要限度,或法律规定可以不予响应的,我们可能拒绝或限制响应,并向您说明理由。',
'3. 账号注销后,我们将停止提供与账号相关的服务,并依法删除或匿名化处理相关个人信息;依法需要保留的信息,在保存期间仅用于履行法定义务或争议处理。注销前,请您按照产品说明妥善迁移或备份用户业务数据。',
'<strong>八、未成年人个人信息</strong>',
'不以不满十四周岁的未成年人应当在父母或其他监护人指导下使用开元云相关服务。我们发现未经监护人同意处理了不满十四周岁未成年人的个人信息时,将依法删除或采取其他必要措施。',
'<strong>九、个人信息跨境提供</strong>',
'1. 如特定服务需要向中华人民共和国境外提供个人信息,我们将仅在业务确有必要且符合法律规定的情况下进行,并在提供前告知境外接收方信息、处理目的和方式、个人信息种类以及您向境外接收方行使权利的方式和程序。我们将依法履行相应程序,取得单独同意,并要求境外接收方达到法律规定的个人信息保护标准。',
'2. 用户自行选择境外资源、境外模型或其他境外服务的,相关数据位置和跨境安排以对应产品说明、订单、合同及单独告知为准。',
'<strong>十、本政策的更新</strong>',
'1. 我们可能根据法律变化、业务调整或个人信息处理活动变化更新本政策。更新后的政策将通过网站、产品页面或其他适当方式发布。处理目的、方式、个人信息种类、保存期限或个人权利等发生重大变化的,我们将以显著方式通知;依法需要重新取得同意的,将在相关处理前完成。',
'2. 未经您的同意,我们不会通过更新本政策减损您依法享有的权利。',
'<strong>十一、如何联系我们</strong>',
'1. 如您对本政策或个人信息处理活动有疑问、意见、投诉,或需要行使个人信息权利,可通过以下方式联系开元云:',
'公司名称:【开元云(北京)科技有限公司】',
'联系地址【北京市朝阳区东三环中路65号富力中心】',
'联系电话【400-6150805 010-65917875】',
'联系邮箱【Open-computing@kaiyuancloud.cn】',
'2. 我们将在核验您的身份后依法处理。对处理结果有异议的,您可以再次向我们反馈,也可以依法向履行个人信息保护职责的部门投诉、举报或寻求其他救济。',
]
def esc(text: str) -> str:
return text.replace('\\', '\\\\').replace("'", "\\'")
def render_paragraphs(items):
lines = []
for item in items:
lines.append(f" '{esc(item)}',")
lines[-1] = lines[-1].rstrip(',')
return lines
root = Path(__file__).resolve().parents[1]
out = root / 'src/views/homePage/agreement/agreementDocs.js'
content = '\n'.join([
'export default {',
" 'user': {",
" 'title': '用户协议',",
" 'paragraphs': [",
*render_paragraphs(USER_PARAGRAPHS),
' ]',
' },',
" 'privacy': {",
" 'title': '隐私政策',",
" 'paragraphs': [",
*render_paragraphs(PRIVACY_PARAGRAPHS),
' ]',
' }',
'}',
'',
])
out.write_text(content, encoding='utf-8')
print(f'Wrote {out}')

View File

@ -0,0 +1,42 @@
import json
import zipfile
import xml.etree.ElementTree as ET
from pathlib import Path
docx = Path(r'd:\电脑管家迁移文件\xwechat_files\wxid_wfmw9gfr2p9u22_fea0\msg\attach\ca2d7449434be57a2cd16ff8c9e33d13\2026-08\Rec\b548997303412ca6\F\0\开元云用户协议- TY20260729.docx')
W = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'
ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
def run_bold(run):
rpr = run.find('w:rPr', ns)
if rpr is None:
return False
bold = rpr.find('w:b', ns)
if bold is None:
return False
val = bold.get(f'{W}val')
return val not in ('0', 'false')
with zipfile.ZipFile(docx) as zf:
root = ET.fromstring(zf.read('word/document.xml'))
paragraphs = []
for paragraph in root.iter(f'{W}p'):
parts = []
for run in paragraph.iter(f'{W}r'):
text = ''.join(t.text or '' for t in run.iter(f'{W}t'))
if not text:
continue
if run_bold(run):
parts.append(f'<strong>{text}</strong>')
else:
parts.append(text)
line = ''.join(parts).strip()
if line:
paragraphs.append(line)
out = Path(__file__).resolve().parents[1] / 'tmp_user_agreement.json'
out.write_text(json.dumps(paragraphs, ensure_ascii=False, indent=2), encoding='utf-8')
print(f'Wrote {len(paragraphs)} paragraphs to {out}')

View File

@ -1,8 +1,7 @@
<template>
<div class="box">
<div>
<div class="contener" v-if="shouldShowFloatingConsult">
<div v-if="shouldShowFloatingConsult" class="contener">
<transition name="slide">
<div v-show="windowsHidden" style="font-size: 14px">
@ -10,7 +9,7 @@
<a href="#" class="floating-consult-btn primary" @click.prevent="openAiConsult">
<div class="floating-consult-icon">
<img src="./img/ocai.jpg" alt="在线咨询">
<span class="consult-badge"></span>
<span class="consult-badge" />
</div>
<!-- <span class="floating-consult-text">在线咨询</span> -->
</a>
@ -18,37 +17,41 @@
</div>
</transition>
</div>
<!-- 申请试用弹窗 -->
<el-dialog title="申请试用产品" :visible.sync="dialogVisible" width="35%" :before-close="handleClose"
custom-class="apply-use">
<el-dialog
title="申请试用产品"
:visible.sync="dialogVisible"
width="35%"
:before-close="handleClose"
custom-class="apply-use"
>
<el-form ref="form" :model="form" label-width="120px" :rules="rules" style="width: 80%">
<el-form-item label="姓名:" prop="customer">
<el-input v-model="form.customer" placeholder="请输入姓名"></el-input>
<el-input v-model="form.customer" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="联系方式:" prop="phone">
<el-input v-model="form.phone" placeholder="请输入联系方式"></el-input>
<el-input v-model="form.phone" placeholder="请输入联系方式" />
</el-form-item>
<el-form-item label="公司:" prop="unit">
<el-input v-model="form.unit" placeholder="请输入公司名称"></el-input>
<el-input v-model="form.unit" placeholder="请输入公司名称" />
</el-form-item>
<el-form-item label="数量:">
<el-input disabled v-model="form.product_num" placeholder="请输入资源数量"></el-input>
<el-input v-model="form.product_num" disabled placeholder="请输入资源数量" />
</el-form-item>
<el-form-item label="需求型号:" prop="resources">
<!-- <el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4}" v-model="form.resources" placeholder="请输入资源需求"></el-input>-->
<el-checkbox-group v-model="form.resources" style="display: flex;flex-wrap: wrap;">
<el-checkbox label="H800" style="width: 50%;"></el-checkbox>
<el-checkbox label="H100" style="width: 50%;"></el-checkbox>
<el-checkbox label="A800" style="width: 50%;"></el-checkbox>
<el-checkbox label="A100" style="width: 50%;"></el-checkbox>
<el-checkbox label="H800" style="width: 50%;" />
<el-checkbox label="H100" style="width: 50%;" />
<el-checkbox label="A800" style="width: 50%;" />
<el-checkbox label="A100" style="width: 50%;" />
</el-checkbox-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose" size="small"> </el-button>
<el-button size="small" @click="handleClose"> </el-button>
<el-button size="small" type="primary" @click="onSubmit()"> </el-button>
</span>
</el-dialog>
@ -56,10 +59,10 @@
<!-- v-if="isShowChangeChat"-->
<div v-if="isShowChangeChat " class="changeChat" style="">
<span style="margin-bottom: 5px;display: block">请选择聊天方式</span>
<el-checkbox-group :min="1" style="margin-bottom: 5px" v-model="checkType">
<el-checkbox label="文字"></el-checkbox>
<el-checkbox label="视频"></el-checkbox>
<el-checkbox label="音频"></el-checkbox>
<el-checkbox-group v-model="checkType" :min="1" style="margin-bottom: 5px">
<el-checkbox label="文字" />
<el-checkbox label="视频" />
<el-checkbox label="音频" />
</el-checkbox-group>
<div style="display: flex;justify-content: flex-end">
<el-button size="mini" @click="closeWindow">关闭</el-button>
@ -74,12 +77,10 @@
</template>
<script>
import {contantAPI, applyAPI} from "../../api/floatingWindow/index";
import axios from "axios";
import {mapState} from "vuex";
import {getCustomerOfSaleUserId} from "@/api/customer/vedio";
import { getHomePath } from "@/views/setting/tools";
import { reqNewHomeConsult } from "@/api/newHome";
import { contantAPI, applyAPI } from '../../api/floatingWindow/index'
import { getCustomerOfSaleUserId } from '@/api/customer/vedio'
import { getHomePath } from '@/views/setting/tools'
import { reqNewHomeConsult } from '@/api/newHome'
export default {
//
@ -87,10 +88,10 @@ export default {
return {
socket: null,
checkType: ['文字'],
isShowChangeChat: false,//
isShowChangeChat: false, //
loading: true,
currentDate: '2021-06-01',
isShowPicLoading: true,//loading
isShowPicLoading: true, // loading
isSend: true,
windowsHidden: true,
// P
@ -98,7 +99,7 @@ export default {
//
isMobile: false,
url: window.location.href,
orgType: "",
orgType: '',
isShow: false,
userid: sessionStorage.getItem('userId'),
src: null,
@ -114,42 +115,22 @@ export default {
},
rules: {
customer: [
{required: true, message: "请输入姓名", trigger: "change"},
{ required: true, message: '请输入姓名', trigger: 'change' }
],
phone: [{pattern: /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/, message: "请输入有效的手机号"},
{required: true, trigger: "blur", message: "请输入手机号"}],
phone: [{ pattern: /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/, message: '请输入有效的手机号' },
{ required: true, trigger: 'blur', message: '请输入手机号' }],
unit: [
{required: true, message: "请输入单位", trigger: 'change'},
{ required: true, message: '请输入单位', trigger: 'change' }
],
product: [
{required: true, message: "请输入资源名称", trigger: 'change'},
{ required: true, message: '请输入资源名称', trigger: 'change' }
],
resources: [
{required: true, message: "请输入资源需求", trigger: 'blur'},
],
},
{ required: true, message: '请输入资源需求', trigger: 'blur' }
]
}
}
},
created() {
this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(this.userAgent);
},
watch: {
'$route': { // $route
handler(to, from) {
this.orgType = sessionStorage.getItem('org_type') ? sessionStorage.getItem('org_type') : "";
this.userid = sessionStorage.getItem('userId') ? sessionStorage.getItem('userId') : "";
},
deep: true, //
immediate: true, //
}
},
mounted() {
// debugger
// console.log("~~~",location.href)
// console.log("~~~",this.$route)
},
computed: {
shouldShowFloatingConsult() {
const isHomePage = [
@ -157,9 +138,28 @@ export default {
'/homePage/indexLast',
'/ncmatchHome/index'
].includes(this.$route.path)
return isHomePage || this.orgType == 2 || this.orgType == 3 || !this.userid
return isHomePage || this.orgType === '2' || this.orgType === '3' || !this.userid
}
},
watch: {
'$route': { // $route
handler(to, from) {
this.orgType = sessionStorage.getItem('org_type') ? sessionStorage.getItem('org_type') : ''
this.userid = sessionStorage.getItem('userId') ? sessionStorage.getItem('userId') : ''
},
deep: true, //
immediate: true //
}
},
created() {
this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(this.userAgent)
},
mounted() {
// debugger
// console.log("~~~",location.href)
// console.log("~~~",this.$route)
},
methods: {
// getHomePath()
getHomePath,
@ -168,21 +168,21 @@ export default {
title: '提示',
message: '当前还未登录,请先登录~',
type: 'warning'
});
})
},
goVedioPage() {
if (!sessionStorage.getItem('userId')) {
console.log("未登录,请重新登录")
console.log('未登录,请重新登录')
this.openTip()
} else {
let ploady = {
const ploady = {
audioIsOn: 0,
vedioIsOn: 0,
chatIsOn: 0,
userId: this.userid,
toUserId: 0,
customerName: sessionStorage.getItem('username'),
customerName: sessionStorage.getItem('username')
}
for (let i = 0; i < this.checkType.length; i++) {
if (this.checkType[i] === '文字') {
@ -194,9 +194,8 @@ export default {
}
}
getCustomerOfSaleUserId({userid: this.userid}).then(res => {
let routeData = {
getCustomerOfSaleUserId({ userid: this.userid }).then(res => {
const routeData = {
chatIsOn: ploady.chatIsOn,
vedioIsOn: ploady.vedioIsOn,
audioIsOn: ploady.audioIsOn,
@ -215,9 +214,9 @@ export default {
})
this.isShowChangeChat = false
// let webSocketUrl = 'wss://www.opencomputing.cn/dev/wss/pub/rtcc.ws'
let webSocketUrl = 'wss://www.opencomputing.cn/pub/rtcc.ws'
const webSocketUrl = 'wss://www.opencomputing.cn/pub/rtcc.ws'
this.socket = new WebSocket(webSocketUrl)
let ploadyed = {
const ploadyed = {
type: 'send',
from: sessionStorage.getItem('userId'),
uuid: res.data,
@ -230,36 +229,47 @@ export default {
// content: {}
// }
this.socket.onopen = (event) => {
console.log("客户创建成功了@@@@@")
console.log("发送的信息是", ploadyed)
this.socket.send(JSON.stringify(ploadyed));
};
console.log('客户创建成功了@@@@@')
console.log('发送的信息是', ploadyed)
this.socket.send(JSON.stringify(ploadyed))
}
this.socket.onmessage = (event) => {
console.log('接收到消息@@@@', event.data);
};
console.log('接收到消息@@@@', event.data)
}
this.socket.onclose = (event) => {
console.log('WebSocket连接已关闭');
};
console.log('WebSocket连接已关闭')
}
} else {
console.log("zouleels")
console.log('zouleels')
}
})
}
},
open2() {
this.isShowChangeChat = true
},
getYunbaoProducts() {
return [
{ id: 'bid', key: this.$t('yunbao.products.bid'), intro: 'E投标智能体是覆盖「招标解析→标书编制→合规审查→查重→知识沉淀」全链路的一站式投标AI解决方案帮企业将编标周期从数天压缩至小时级低级废标率降低100%。' },
{ id: 'tender', key: this.$t('yunbao.products.tender'), intro: 'E招标智能体AI辅助编制招标文件自动合规性审查让招标流程更高效、更透明、更合规。' },
{ id: 'evaluation', key: this.$t('yunbao.products.evaluation'), intro: 'E评标智能体AI辅助评标分析自动提取关键指标、横向对比评分、识别异常报价帮助评标专家高效、公正地完成评审工作。' },
{ id: 'loggingReview', key: this.$t('yunbao.products.loggingReview'), intro: '面向林业管理的行业智能体,可在线完成采伐申请材料的智能核验,自动比对采伐范围、树种、蓄积量等核心指标与合规要求,快速识别违规申请,助力林业资源可持续利用。' },
{ id: 'gasMonitor', key: this.$t('yunbao.products.gasMonitor'), intro: '能源领域工业智能体实时采集燃机运行的温度、压力、振动等多维度数据通过AI算法识别异常运行征兆提前预判潜在故障保障燃机稳定运行降低运维成本。' },
{ id: 'powerPrice', key: this.$t('yunbao.products.powerPrice'), intro: '面向能源行业的预测智能体,结合历史电价数据、供需变化、政策调整、天气影响等多维度变量,通过机器学习模型实现不同周期的电价精准预测,帮助电力企业优化收益管理。' },
{ id: 'comic', key: this.$t('yunbao.products.comic'), intro: '互联网内容创作智能体覆盖从剧本生成、分镜拆解、素材生成到视频合成的全流程制作。支持工业化批量生产帮助中小团队低成本快速产出AI漫画作品大幅降低创作门槛。' },
{ id: 'contract', key: this.$t('yunbao.products.contract'), intro: this.$t('casePages.contract.heroDesc') },
{ id: 'decision', key: this.$t('yunbao.products.decision'), intro: this.$t('casePages.decision.heroDesc') }
]
},
openAiConsult() {
this.resetYunbaoChatInstance()
this.installYunbaoChat()
window.YunbaoChat.init({
avatarUrl: require('./img/ocai.jpg'),
name: '云宝小助手'
name: this.$t('yunbao.name'),
products: this.getYunbaoProducts()
})
window.YunbaoChat.open()
},
@ -287,22 +297,12 @@ export default {
this._inited = true
this._config = Object.assign({
avatarUrl: '',
name: '云宝小助手',
name: vm.$t('yunbao.name'),
submitUrl: '',
products: [
{ key: 'E投标', intro: 'E投标智能体是覆盖「招标解析→标书编制→合规审查→查重→知识沉淀」全链路的一站式投标AI解决方案帮企业将编标周期从数天压缩至小时级低级废标率降低100%。' },
{ key: 'E招标', intro: 'E招标智能体AI辅助编制招标文件自动合规性审查让招标流程更高效、更透明、更合规。' },
{ key: 'E评标', intro: 'E评标智能体AI辅助评标分析自动提取关键指标、横向对比评分、识别异常报价帮助评标专家高效、公正地完成评审工作。' },
{ key: '采伐智审', intro: '面向林业管理的行业智能体,可在线完成采伐申请材料的智能核验,自动比对采伐范围、树种、蓄积量等核心指标与合规要求,快速识别违规申请,助力林业资源可持续利用。' },
{ key: '燃机智慧监盘', intro: '能源领域工业智能体实时采集燃机运行的温度、压力、振动等多维度数据通过AI算法识别异常运行征兆提前预判潜在故障保障燃机稳定运行降低运维成本。' },
{ key: '电价预测', intro: '面向能源行业的预测智能体,结合历史电价数据、供需变化、政策调整、天气影响等多维度变量,通过机器学习模型实现不同周期的电价精准预测,帮助电力企业优化收益管理。' },
{ key: 'AI漫剧制作', intro: '互联网内容创作智能体覆盖从剧本生成、分镜拆解、素材生成到视频合成的全流程制作。支持工业化批量生产帮助中小团队低成本快速产出AI漫画作品大幅降低创作门槛。' },
{ key: '合同智能审查', intro: 'AI驱动的办公智能体可快速识别合同中的风险条款、表述歧义、合规漏洞自动标注问题位置并给出修改建议。支持多类型合同模板适配大幅缩短人工审查时长。' },
{ key: '投策智能体', intro: '面向企业投资决策的辅助智能体,整合多维度市场数据、行业趋势与政策信息,通过算法模拟不同决策场景的收益与风险,自动生成可视化分析报告,提升投资方案科学性。' }
],
products: vm.getYunbaoProducts(),
pages: {
'合同智能审查': '/homePage/agentStore/contractCase',
'投策智能体': '/homePage/agentStore/decisionCase'
contract: '/homePage/agentStore/contractCase',
decision: '/homePage/agentStore/decisionCase'
}
}, config)
this.injectCSS()
@ -353,9 +353,9 @@ export default {
if (!body) return
body.innerHTML = ''
setTimeout(() => {
this.addBotMsg('嗨~我是云宝 👋<br>请问您想随便看看,还是直接聊聊需求?', [
{ text: '随便看看', action: 'browse' },
{ text: '直接聊聊需求', action: 'direct' }
this.addBotMsg(vm.$t('yunbao.welcome'), [
{ text: vm.$t('yunbao.browse'), action: 'browse' },
{ text: vm.$t('yunbao.direct'), action: 'direct' }
])
}, 200)
},
@ -373,7 +373,7 @@ export default {
<div class="yb-chat-product-card" data-action="${item.action || ''}" data-param="${item.param || ''}" data-url="${item.url || ''}" data-text="${item.text || ''}">
<div class="yb-chat-product-card-title">${item.text}</div>
<div class="yb-chat-product-card-desc">${item.desc || ''}</div>
<span class="yb-chat-product-card-link">查看更多 </span>
<span class="yb-chat-product-card-link">${vm.$t('yunbao.learnMore')}</span>
</div>
`).join('')}</div>`
} else if (type === 'tags') {
@ -383,7 +383,7 @@ export default {
}
}
msg.innerHTML = `
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="云宝"></div>
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="${this._config.name}"></div>
<div>
<div class="yb-chat-msg-bubble">${html}</div>
${optionHtml}
@ -413,43 +413,43 @@ export default {
}
if (action === 'browse') {
setTimeout(() => {
this.addBotMsg('好的~为您推荐我们的热门产品 👇', [
{ text: 'E投标', desc: '更智能的标书写作引擎', action: 'goExternal', url: 'https://bid-ocai-v2.jinan.opencomputing.cn/', type: 'cards' },
{ text: '合同智能审查', desc: 'AI驱动合同风险审查效率提升60%+', action: 'goContract', type: 'cards' },
{ text: '投策智能体', desc: '分钟级投研分析,精准辅助投资决策', action: 'goInvest', type: 'cards' }
this.addBotMsg(vm.$t('yunbao.recommend'), [
{ text: vm.$t('yunbao.products.bid'), desc: vm.$t('yunbao.productDescs.bid'), action: 'goExternal', url: 'https://bid-ocai-v2.jinan.opencomputing.cn/', type: 'cards' },
{ text: vm.$t('yunbao.products.contract'), desc: vm.$t('yunbao.productDescs.contract'), action: 'goContract', type: 'cards' },
{ text: vm.$t('yunbao.products.decision'), desc: vm.$t('yunbao.productDescs.decision'), action: 'goInvest', type: 'cards' }
])
setTimeout(() => {
this.addBotMsg('或者您还有其他想了解的产品吗?', this.getProductTags(), 'tags')
this.addBotMsg(vm.$t('yunbao.moreProducts'), this.getProductTags(), 'tags')
}, 1200)
}, 200)
return
}
if (action === 'direct') {
setTimeout(() => {
this.addBotMsg('您想了解哪方面的产品或服务呢?', this.getProductTags(), 'tags')
this.addBotMsg(vm.$t('yunbao.askProduct'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goContract') {
vm.$router.push(this._config.pages['合同智能审查'] || '/homePage/agentStore/contractCase').catch(() => {})
vm.$router.push(this._config.pages.contract || '/homePage/agentStore/contractCase').catch(() => {})
this.close()
setTimeout(() => {
this.addBotMsg('已为您打开合同智能审查页面 📄<br>还有其他想了解的吗?', this.getProductTags(), 'tags')
this.addBotMsg(vm.$t('yunbao.openedContract'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goExternal') {
window.open(url, '_blank')
setTimeout(() => {
this.addBotMsg('已为您打开相关页面。还有其他想了解的吗?', this.getProductTags(), 'tags')
this.addBotMsg(vm.$t('yunbao.openedPage'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goInvest') {
vm.$router.push(this._config.pages['投策智能体'] || '/homePage/agentStore/decisionCase').catch(() => {})
vm.$router.push(this._config.pages.decision || '/homePage/agentStore/decisionCase').catch(() => {})
this.close()
setTimeout(() => {
this.addBotMsg('已为您打开投策智能体页面 📊<br>还有其他想了解的吗?', this.getProductTags(), 'tags')
this.addBotMsg(vm.$t('yunbao.openedDecision'), this.getProductTags(), 'tags')
}, 200)
return
}
@ -467,12 +467,16 @@ export default {
return this._config.products.map(item => ({
text: item.key,
action: 'productIntro',
param: item.key
param: item.id
}))
},
getProductIntro(key) {
const product = this._config.products.find(item => item.key === key)
return product ? product.intro : '这是一款优秀的AI产品欢迎进一步了解'
const product = this._config.products.find(item => item.id === key || item.key === key)
return product ? product.intro : vm.$t('yunbao.productIntroDefault')
},
getProductName(key) {
const product = this._config.products.find(item => item.id === key || item.key === key)
return product ? product.key : key
},
addContactForm() {
const body = document.getElementById('yunbaoChatBody')
@ -481,16 +485,16 @@ export default {
const form = document.createElement('div')
form.className = 'yb-chat-msg'
form.innerHTML = `
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="云宝"></div>
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="${this._config.name}"></div>
<div>
<div class="yb-chat-msg-bubble">
请留下您的联系方式我们的顾问将尽快与您联系 😊
${vm.$t('yunbao.consultantNote')}
<div class="yb-chat-form">
<input type="text" class="yb-chat-form-input" id="yunbaoChatName" placeholder="您的姓名">
<input type="tel" class="yb-chat-form-input" id="yunbaoChatPhone" placeholder="联系电话">
<input type="text" class="yb-chat-form-input" id="yunbaoChatCompany" placeholder="公司名称">
<button class="yb-chat-form-submit" id="yunbaoChatSubmit">提交咨询</button>
<div class="yb-chat-form-tip">信息仅用于顾问联系</div>
<input type="text" class="yb-chat-form-input" id="yunbaoChatName" placeholder="${vm.$t('contactSales.namePlaceholder')}">
<input type="tel" class="yb-chat-form-input" id="yunbaoChatPhone" placeholder="${vm.$t('contactSales.phonePlaceholder')}">
<input type="text" class="yb-chat-form-input" id="yunbaoChatCompany" placeholder="${vm.$t('contactSales.companyPlaceholder')}">
<button class="yb-chat-form-submit" id="yunbaoChatSubmit">${vm.$t('yunbao.submit')}</button>
<div class="yb-chat-form-tip">${vm.$t('yunbao.infoNote')}</div>
</div>
</div>
</div>
@ -505,28 +509,29 @@ export default {
const company = document.getElementById('yunbaoChatCompany').value.trim()
const submitBtn = document.getElementById('yunbaoChatSubmit')
if (!name || !phone) {
this.addBotMsg('请先填写姓名和联系电话哦~')
this.addBotMsg(vm.$t('yunbao.nameRequired'))
return
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
this.addBotMsg('请输入正确的 11 位手机号哦~')
this.addBotMsg(vm.$t('yunbao.phoneInvalid'))
return
}
if (submitBtn && submitBtn.disabled) return
if (submitBtn) {
submitBtn.disabled = true
submitBtn.innerText = '提交中...'
submitBtn.innerText = vm.$t('yunbao.submitting')
}
this.addUserMsg('已提交联系方式')
this.addUserMsg(vm.$t('yunbao.submitted'))
const productName = this.getProductName(this._selectedProduct)
const data = {
custom_type: '1',
name,
phone,
company,
email: '',
content: this._selectedProduct ? `我想咨询关于【${this._selectedProduct}】的产品信息` : '云宝对话咨询',
content: this._selectedProduct ? vm.$t('yunbao.consultingContent').replace('{product}', productName) : vm.$t('yunbao.defaultContent'),
source: '官网',
url_link: window.location.href
}
@ -534,20 +539,20 @@ export default {
try {
const response = await reqNewHomeConsult(data)
if (response && response.status) {
this.addBotMsg('收到!我们的顾问将尽快与您联系 🎉<br>感谢您的信任!')
this.addBotMsg(vm.$t('yunbao.success'))
return
}
this.addBotMsg((response && response.msg) || '提交失败了,您可以稍后重试。', [
{ text: '重新提交', action: 'retrySubmit', primary: true }
this.addBotMsg((response && response.msg) || vm.$t('yunbao.submitFail'), [
{ text: vm.$t('yunbao.retry'), action: 'retrySubmit', primary: true }
])
} catch (error) {
this.addBotMsg('网络开小差了,提交失败,您可以重试一次。', [
{ text: '重新提交', action: 'retrySubmit', primary: true }
this.addBotMsg(vm.$t('yunbao.networkFail'), [
{ text: vm.$t('yunbao.retry'), action: 'retrySubmit', primary: true }
])
} finally {
if (submitBtn) {
submitBtn.disabled = false
submitBtn.innerText = '提交咨询'
submitBtn.innerText = vm.$t('yunbao.submit')
}
}
}
@ -558,10 +563,10 @@ export default {
<div id="yunbaoModal" class="yb-assistant-modal-overlay">
<div class="yb-assistant-modal">
<div class="yb-assistant-modal-header">
<div class="yb-chat-avatar"><img src="${config.avatarUrl}" alt="云宝"></div>
<div class="yb-chat-avatar"><img src="${config.avatarUrl}" alt="${config.name}"></div>
<div class="yb-chat-header-info">
<div class="yb-chat-header-name">${config.name}</div>
<div class="yb-chat-header-status">在线</div>
<div class="yb-chat-header-status">${this.$t('yunbao.online')}</div>
</div>
<button class="yb-assistant-close-btn" id="yunbaoCloseBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
@ -626,7 +631,7 @@ export default {
@media(max-width:480px){.yb-assistant-modal{width:calc(100vw - 32px);height:calc(100vh - 140px);right:0}.yb-assistant-modal-overlay{right:16px;bottom:90px}}
`
},
//
//
closeWindow() {
this.isShowChangeChat = false
},
@ -634,14 +639,14 @@ export default {
this.isShowPicLoading = false
console.log()
},
handleMouseEnter() {//
handleMouseEnter() { //
this.isShow = true
if (this.isSend) {
this.contant()
}
// this.contant()
},
handleMouseLeave() {//
handleMouseLeave() { //
this.isSend = true
this.src = ''
this.phone = ''
@ -649,11 +654,11 @@ export default {
this.isShow = false
this.isShowPicLoading = true
},
contant() {//
let params = {
contant() { //
const params = {
// userid: sessionStorage.getItem("userId")
}
if (this.url.indexOf('www') != -1) {
if (this.url.indexOf('www') !== -1) {
params.domain = 'www'
}
contantAPI(params).then(res => {
@ -661,70 +666,65 @@ export default {
this.isShowPicLoading = false
if (res.status) {
this.src = res.picture_url
this.phone = res.contactor_phone
} else {
this.$message({
message: res.msg,
type: "error",
});
type: 'error'
})
}
})
},
onSubmit() {//
onSubmit() { //
this.$refs.form.validate((valid) => {
if (valid) {
let pamars = {
const pamars = {
customer: this.form.customer,
phone: this.form.phone,
unit: this.form.unit,
resources: this.form.resources,
userid: sessionStorage.getItem("userId")
userid: sessionStorage.getItem('userId')
}
applyAPI(pamars).then(res => {
if (res.status) {
this.dialogVisible = false
this.$message({
message: "成功申请试用",
type: "success",
});
message: '成功申请试用',
type: 'success'
})
} else {
this.$message({
message: res.msg,
type: "error",
});
type: 'error'
})
}
})
}
})
},
tryUse() {//
if (sessionStorage.getItem("userId")) {
tryUse() { //
if (sessionStorage.getItem('userId')) {
this.dialogVisible = true
} else {
// window.open('https://www.opencomputing.cn/#/floatingBox')
this.$router.push('/floatingBox')
}
},
handleClose() {
this.$refs.form.resetFields();
this.$refs.form.resetFields()
this.dialogVisible = false
},
//
//
isShowFloating() {
return false
}
}
};
}
</script>
<style lang="scss" scoped>
.box {
.contener {
.dialog {
width: 400px;
@ -1082,13 +1082,11 @@ export default {
width: .38rem;
flex-direction: column;
&:hover {
.cloud-contact-us-i {
background-position: -100px 0
}
//.active {
// border: 5px solid red;
// background-color: white !important;
@ -1319,7 +1317,6 @@ export default {
letter-spacing: 2px;
}
</style>
<style>
.apply-use {

View File

@ -33,6 +33,10 @@ export default {
viewMore: 'View More →',
footerProducts: 'Products & Services',
footerContact: 'Contact Us',
footerAddress: 'Address',
footerEmail: 'Email',
footerTel: 'Tel',
followOfficialAccount: 'Follow Official Account',
onlineChat: 'Online Chat',
solutionCards: {
collaboration: {
@ -160,5 +164,242 @@ export default {
secondDesc: 'Recognized for its industrial-grade AI agent factory delivery capabilities and benchmark cases among central and state-owned enterprises, Open Computing AI was named a Forbes China AI Commercial Application Demonstration Enterprise — underscoring its leadership in turning AI technology into scalable, real-world industry solutions.'
}
},
about: {
intro: {
kicker: 'About Us',
title: 'About Us',
copyHtml: 'Open Computing AI takes <strong class="copy-strong">"Make AI Everywhere, Make AI Easy"</strong> as its mission. By empowering all industries through integrated technologies, we strive to become a world-leading operator of AI Agent services. The company focuses on key application scenarios including <strong class="copy-strong">education &amp; research, engineering &amp; transportation, port &amp; water utilities, energy &amp; power, and life-science &amp; healthcare</strong>. We build full-stack AI solutions to drive the industrial intelligent transformation. As a Specialized, Refined, Differentiated and Innovative Enterprise, National High-Tech Enterprise, Tech-Based SME and Innovative SME, the company has obtained <span class="copy-nowrap">ISO&nbsp;9001, ISO&nbsp;27001 and ISO&nbsp;28000</span> certifications. In 2026, it was selected as one of Forbes Chinas AI Commercial Implementation Demonstration Enterprises. We have established in-depth cooperation with top-tier institutions such as Peking University Science and Technology Park (PKUSTP), Zhongguancun NCMatch, Inspur Yunzhou, China Railway Group Smart City R&amp;D Center, Beibu Gulf Port Big Data, Baidu Intelligent Cloud and Alibaba Cloud. Leveraging our self-developed AI Agent Factory, we have achieved dual breakthroughs in AI model services and commercial value. Open Computing AI will continue to deepen the scenario-based implementation of AI in vertical industries to accelerate the realization of our strategic vision.'
},
advantages: {
kicker: 'Why Choose Us',
title: 'Why Choose Open Computing AI',
fast: {
title: 'Faster',
subtitle: 'Ultra-fast inference · Compute efficiency',
tag: 'AI Infra',
desc: 'Dramatically accelerates model inference and provides a solid computing infrastructure foundation for enterprise efficiency.'
},
accurate: {
title: 'More Accurate',
subtitle: 'Vertical adaptation · Truth-oriented results',
tag: 'AI Agent',
desc: 'Provides model pre-training, dedicated knowledge bases, and ontology services for vertical industry scenarios.'
},
strong: {
title: 'Stronger',
subtitle: 'Full-stack capability · Human-AI collaboration',
tag: 'AI Ability',
desc: 'Brings globally leading AI capability models into real-world scenarios and continuously enhances AI controllability.'
},
stable: {
title: 'More Stable',
subtitle: 'Private deployment · Secure and reliable',
tag: 'AI Safety',
desc: 'Runs large models and agents stably in dedicated private-domain scenarios, backed by national-level professional teams.'
}
},
credentials: {
kicker: 'Credentials',
title: 'Credentials & Honors',
highTech: {
title: 'National High-Tech Enterprise',
desc: 'An innovative enterprise recognized by the state in high-tech fields'
},
specialized: {
title: 'Specialized, Refined, Differentiated and Innovative Enterprise',
desc: 'Specialized, Refined, Differentiated, and Innovative development direction'
},
techSme: {
title: 'Tech-Based SME',
desc: 'Certification for small and medium-sized enterprises with technological innovation capabilities'
},
iso: {
title: 'ISO 9001/27001/28000',
desc: 'Triple certification in quality management, information security, and supply chain security'
},
innovative: {
title: 'Innovative SME',
desc: 'An enterprise with high innovation capability and growth potential'
},
forbes: {
title: 'Forbes China',
descPrefix: 'Selected as ',
descHighlight: '"Forbes China AI Commercial Implementation Demonstration Enterprise"',
descSuffix: ' in 2026'
}
},
cta: {
title: 'Join Hands with Open Computing AI to Build an Intelligent Future',
desc: 'Whether you are seeking AI solutions or a like-minded partner, we look forward to speaking with you.'
}
},
newsView: {
badge: 'COMPANY NEWS',
title: 'Corporate News',
intro: 'Stay up to date with Open Computing AI, explore the latest AI industry insights, and witness the intelligent leap with us.',
detail: 'Details',
all: 'All',
loadFail: 'Failed to load news list',
categories: {
corporate: 'Corporate News',
product: 'Product News',
industry: 'Industry Insights',
event: 'Event News'
}
},
casePages: {
decision: {
heroTitle: 'Investment Strategy Agent',
heroDesc: 'An AI-powered assistant designed to support enterprise investment decision-making. It integrates multi-dimensional market data, industry trends, and policy information, and simulates returns and risks across different decision scenarios through algorithms, automatically generating visual analysis reports. It helps enterprises quickly synthesize core information, anticipate market directions, reduce decision-making bias, and enhance the scientific rigor and feasibility of investment proposals.',
tabs: { scenarios: 'Use Cases', solution: 'Solutions', highlights: 'Key Highlights' },
scenariosTitle: 'Application Scenarios',
scenariosDesc: 'Covering the full lifecycle of enterprise investment decision-making',
scenarios: [
{ title: 'Investment Feasibility Study', desc: 'Collects industry data, market trends, and policy information and generates professional investment feasibility analysis reports, helping decision-makers rapidly evaluate project value and risks.' },
{ title: 'Market Research & Analysis', desc: 'Integrates multi-dimensional market data, automatically analyzes market size, competitive landscape, and development trends, and generates detailed market research reports to support business decisions.' },
{ title: 'Competitive Product Analysis', desc: 'Automatically collects competitive product information, analyzes product features, market strategies, and user feedback, and generates competitive comparison reports to help enterprises develop differentiated competitive strategies.' }
],
solutionTitle: 'Challenges & Solutions for Enterprise Decision-Making',
solutionDesc: 'Focusing on data collection, research writing, knowledge management, and intelligent applications',
challengeTitle: 'Challenge: Data-Rich, Insight-Poor',
challenges: [
{ title: 'Severe Data Silos', desc: 'Data is scattered across different business systems or website sources, making it difficult to integrate, which impedes comprehensive analysis and decision-making.' },
{ title: 'Difficulty in Knowledge Accumulation', desc: "Key business knowledge and expert experience primarily reside in individuals' minds and are lost with personnel turnover." },
{ title: 'Time-Consuming and Labor-Intensive Report Writing', desc: 'Manually organizing data and producing high-quality decision reports is cumbersome and inefficient, making it difficult to respond quickly to demands.' }
],
abilityTitle: 'Solutions: Core Capabilities of the E-Decision Platform',
abilityDesc: 'Focusing on four dimensions - data collection, research writing, knowledge management, and intelligent applications - to help enterprises build proprietary knowledge systems and empower scientific decision-making.',
abilities: [
{ title: 'Data Collection & Integration', desc: 'Automatically captures internal and external data sources, breaks down barriers, and unifies data standards.' },
{ title: 'Knowledge Management & Accumulation', desc: 'Transforms unstructured documents into structured knowledge graphs, accumulating core enterprise assets.' },
{ title: 'Intelligent Applications & Q&A', desc: 'Supports natural language queries for rapid retrieval and responses, delivering key insights on demand.' },
{ title: 'AI-Assisted Research Report Writing', desc: 'Accepts a topic input to automatically generate content, with one-click export to PDF/PPT.' }
],
highlightsTitle: 'Project Highlights',
highlightsDesc: 'One Research, Dual-Format Delivery',
highlights: [
{ title: 'One-Click PDF Research Report Generation', desc: 'After AI-assisted generation of research content, the system supports one-click export to a well-formatted, detailed PDF research report, meeting archiving and in-depth reading needs.' },
{ title: 'One-Click PPT Presentation Generation', desc: 'In addition to PDF, the system supports one-click export to PPT presentations with automatic logical structuring, intelligent pagination, and professional formatting - ready to use immediately.' }
],
ctaTitle: 'Start Using the Investment Strategy Agent',
ctaDesc: 'Let AI empower your investment decisions with one research workflow and dual-format delivery.',
contactSales: 'Contact Sales'
},
contract: {
heroTitle: 'Smart Contract Review',
heroDesc: 'A professional review agent designed for the entire contract signing process of enterprise legal and business teams. It aggregates multi-dimensional information including regulatory provisions, internal corporate risk control standards, and historical contract cases. Leveraging the deep semantic parsing capabilities of large language models, it automatically identifies legal risks in contracts and intelligently generates standardized modification suggestions along with clear risk explanations.',
tabs: { scenarios: 'Use Cases', solution: 'Solutions', highlights: 'Key Highlights' },
scenariosTitle: 'Application Scenarios',
scenariosDesc: 'Covering the full lifecycle of the contract review process',
scenarios: [
{ title: 'Business Contract Preliminary Review', desc: 'Automatically parse general business contracts including sales, services, leasing, and cooperation agreements. Screen risk points against enterprise risk control red lines on a clause-by-clause basis, generate preliminary review opinions, reduce basic legal review workload, and accelerate business pre-approval processes.' },
{ title: 'In-depth Risk Control for Complex Commercial Contracts', desc: 'For high-risk specialized contracts involving investment & financing, intellectual property, engineering, confidentiality and non-compete, conduct multi-level risk simulations integrated with complete legal provisions and judicial precedents. Identify deep-seated issues such as authority loopholes, breach defects, and jurisdictional disputes, and generate comprehensive risk assessment documents.' },
{ title: 'Multi-party Contract Version Comparison & Revision', desc: 'Automatically identify differences across multiple revision rounds between both parties, distinguish newly added, deleted, and modified clauses, highlight risk-related changes, and simultaneously generate version comparison ledgers to support business negotiations and legal review, avoiding overlooked key risks during revisions.' }
],
deleted: 'Deleted',
added: 'Added',
solutionTitle: 'Challenges & Solutions in Enterprise Contract Management',
solutionDesc: 'Across four core dimensions: data aggregation, contract review, knowledge accumulation, and intelligent consultation',
challengeTitle: 'Current Challenges',
challenges: [
{ title: 'Fragmented and Dispersed Document Information', desc: 'Contracts, regulations, historical precedents, and internal templates are scattered across different storage channels with no unified search entry, requiring cross-document repeated verification during review.' },
{ title: 'Risk Control Experience Difficult to Retain and Reuse', desc: "Senior legal counsel's review points, negotiation baselines, and risk handling experience reside only with individuals, which often leads to inconsistent standards after personnel handover." },
{ title: 'Time-Consuming Manual Review with Weak Standardization', desc: 'Manual clause-by-clause review of massive contracts consumes significant manpower, while review standards vary among legal staff, resulting in slow responses for urgent signing scenarios.' }
],
abilityTitle: 'Solutions',
abilities: [
{ title: 'Unified Aggregation & Parsing of Multi-source Documents', desc: 'Batch upload PDF, Word, and scanned contracts; OCR recognizes text and image content, and uniformly extracts key information including transaction parties, pricing, performance, and breach clauses in structured format.' },
{ title: 'AI-powered Full-Clause Intelligent Review & Correction', desc: 'Layer-by-layer scan of all contract clauses, marking high, medium, and low risks against laws, regulations, and enterprise internal control rules, with standardized compliance replacement clauses provided.' },
{ title: 'Legal Knowledge Base Accumulation & Management', desc: 'Transform enterprise standard templates, review checklists, precedents, and internal risk control policies into a structured knowledge base, accumulating enterprise-specific legal assets.' },
{ title: 'Natural Language Legal Intelligent Q&A', desc: 'Enables business and legal staff to query compliance requirements, clause drafting, and risk consequences using natural language questions, with instant professional answers and reference clauses.' }
],
highlightsTitle: 'Project Highlights',
highlightsDesc: 'Full-Process Intelligent Risk Control with Four Core Review Capabilities',
highlights: [
{ title: 'Auto-tagged Risk Levels with Compliance Remediation Clauses', desc: 'Classify risks into three levels: critical, general, and advisory. Precisely locate the corresponding original text paragraphs for each risk, and match replacement clauses aligned with enterprise policies and current laws for each risk item.' },
{ title: 'Intelligent Multi-version Contract Comparison & Traceability', desc: 'Upload new and old contracts along with exchanged drafts between both parties; the system automatically highlights added, deleted, and modified clauses, and generates a traceable comparison ledger.' },
{ title: 'All-Format Contract Recognition with Precise Scanned Document Parsing', desc: 'Supports uploading of Word, PDF, scanned images, and stamped document files with built-in high-precision OCR, covering both existing and newly added contract documents.' },
{ title: 'One-Click Reuse of Enterprise Legal Knowledge for Unified Review Standards', desc: 'Built-in enterprise-specific contract template library, risk control red-line checklist, and industry precedent database; new employees can directly adopt mature review standards.' }
]
}
},
contactSales: {
title: 'Contact Sales',
nameLabel: '1. Please enter your name',
namePlaceholder: 'Please enter your name',
phoneLabel: '2. Please enter your contact information',
phonePlaceholder: 'Please enter your phone number',
emailLabel: '3. Please enter your email',
emailPlaceholder: 'Please enter your email',
companyLabel: '4. Please enter your company name',
companyPlaceholder: 'Please enter your company name',
enterpriseLabel: '5. Please select your enterprise type (single choice)',
provinceLabel: '6. Please select your province (single choice)',
provincePlaceholder: 'Enter province name or pinyin initials to search...',
messageLabel: '7. If you have other questions, please leave a message',
messagePlaceholder: 'Please enter your inquiry...',
privacy: 'The information you provide will only be used for this business communication. The company will strictly implement information security protection mechanisms and will not disclose or misuse any of your personal data.',
phoneInvalid: 'Please enter a valid phone number',
emailInvalid: 'Please enter a valid email address',
enterpriseRequired: 'Please select your enterprise type',
provinceRequired: 'Please select your province',
privacyRequired: 'Please agree to the privacy notice before submitting.',
formInvalid: 'Please complete the form.',
cancel: 'Cancel',
submit: 'Submit Inquiry',
qrcode: 'Scan QR code to add official customer service',
enterpriseOptions: {
largeEnterprise: 'Large Enterprise',
sme: 'SME',
opcIndividual: 'OPC / Individual',
university: 'Academy / Institute',
government: 'Government',
other: 'Other'
}
},
yunbao: {
name: 'Yunbao Assistant',
online: 'Online',
welcome: "Hi~ I'm Yunbao 👋<br>Would you like to just browse, or chat about your needs directly?",
browse: 'Just Browse',
direct: 'Chat About Needs',
recommend: 'Sure~ Here are our recommended hot products 👇',
moreProducts: "Or are there other products you'd like to learn about?",
askProduct: 'Which product or service would you like to learn about?',
learnMore: 'Learn More →',
submit: 'Submit Inquiry',
consultantNote: 'Please leave your contact information, and our consultant will reach out to you soon',
infoNote: 'Your information will only be used for consultant contact',
products: {
bid: 'AI Bidding Platform',
tender: 'AI Tendering Platform',
evaluation: 'AI Evaluation Platform',
loggingReview: 'Logging Review',
gasMonitor: 'Gas Turbine Smart Monitoring',
powerPrice: 'Power Price Forecasting',
comic: 'AI Comic Drama Production',
contract: 'Smart Contract Review',
decision: 'Investment Strategy Agent'
},
productDescs: {
bid: 'Smarter bid document writing engine',
contract: 'AI-driven contract risk review, 60%+ efficiency boost',
decision: 'Minute-level investment research analysis, precise decision support'
},
productIntroDefault: 'This is an excellent AI product. Feel free to learn more.',
nameRequired: 'Please enter your name and phone number first.',
phoneInvalid: 'Please enter a valid 11-digit phone number.',
submitted: 'Contact information submitted',
consultingContent: 'I would like to inquire about {product}.',
defaultContent: 'Yunbao chat consultation',
submitting: 'Submitting...',
success: 'Received! Our consultant will contact you soon.<br>Thank you for your trust!',
submitFail: 'Submission failed. Please try again later.',
networkFail: 'Network error. Submission failed. Please try again.',
retry: 'Retry',
openedContract: 'The Smart Contract Review page has been opened.<br>Anything else you would like to know?',
openedDecision: 'The Investment Strategy Agent page has been opened.<br>Anything else you would like to know?',
openedPage: 'The related page has been opened. Anything else you would like to know?'
},
...autoMessages
}

View File

@ -33,6 +33,10 @@ export default {
viewMore: '查看更多 →',
footerProducts: '产品服务',
footerContact: '联系我们',
footerAddress: '地址',
footerEmail: '邮箱',
footerTel: '电话',
followOfficialAccount: '关注公众号',
onlineChat: '在线咨询',
solutionCards: {
collaboration: {
@ -160,5 +164,242 @@ export default {
secondDesc: '凭借 AI 智能体工厂的工业级交付能力与央国企标杆案例,开元云入选福布斯中国人工智能商业落地示范企业。'
}
},
about: {
intro: {
kicker: 'About Us',
title: '关于我们',
copyHtml: '开元云科技Open Computing AI以<strong class="copy-strong">"让AI无处不在让智能如此简单"</strong>为使命通过融合技术赋能千行百业致力于成为全球领先的AI智能体服务运营商。公司聚焦<strong class="copy-strong">教育科研、工程交通、港口水务、能源电力、生物医药</strong>等战略应用场景构建全栈AI解决方案推动产业智能化升级。作为专精特新企业国家级高新技术企业、科技型中小企业、创新型中小企业和<span class="copy-nowrap">ISO&nbsp;9001/27001/28000</span>认证单位2026年入选福布斯中国"AI商业落地示范企业"。与北京大学科创园、中关村NCMatch、浪潮云洲、中国中铁智慧城市研发中心、北港大数据、百度智能云、阿里云等顶尖机构建立深度合作。依托自主研发的AI智能体工厂实现AI模型服务与商业价值的双重突破。开元云将持续深耕垂直领域AI场景化落地加速实现战略愿景。'
},
advantages: {
kicker: 'Why Choose Us',
title: '为什么选择开元云',
fast: {
title: '更快',
subtitle: '极速推理 · 算力提效',
tag: 'AI Infra',
desc: '翻倍级拉升模型推理速度,为企业提效提供坚实算力基础设施'
},
accurate: {
title: '更准',
subtitle: '垂类适配 · 去幻求真',
tag: 'AI Agent',
desc: '针对垂类行业场景开展模型预训练、专属知识库与本体论服务'
},
strong: {
title: '更强',
subtitle: '全栈能力 · 人机协同',
tag: 'AI Ability',
desc: '全球领先AI能力模型下沉落地AI掌控力持续增强'
},
stable: {
title: '更稳',
subtitle: '私有部署 · 安全可信',
tag: 'AI Safety',
desc: '专属私域场景稳定运行大模型与智能体,携手国家级专业团队为您护航'
}
},
credentials: {
kicker: 'Credentials',
title: '资质与荣誉',
highTech: {
title: '国家级高新技术企业',
desc: '经国家认定的高新技术领域创新型企业'
},
specialized: {
title: '专精特新企业',
desc: '专业化、精细化、特色化、新颖化发展方向'
},
techSme: {
title: '科技型中小企业',
desc: '具备科技创新能力的中小型企业认定'
},
iso: {
title: 'ISO 9001/27001/28000',
desc: '质量管理、信息安全、供应链安全三重认证'
},
innovative: {
title: '创新型中小企业',
desc: '具有较高创新能力和发展潜力的企业'
},
forbes: {
title: '福布斯中国',
descPrefix: '2026年入选',
descHighlight: '"AI商业落地示范企业"',
descSuffix: ''
}
},
cta: {
title: '携手开元云,共筑智能未来',
desc: '无论您是寻求AI解决方案的企业还是志同道合的合作伙伴我们期待与您对话'
}
},
newsView: {
badge: 'COMPANY NEWS',
title: '企业动态',
intro: '了解开元云最新动态把握AI行业前沿资讯与我们一起见证智能跃迁',
detail: '详情',
all: '全部',
loadFail: '新闻列表加载失败',
categories: {
corporate: '企业动态',
product: '产品动态',
industry: '行业洞察',
event: '活动资讯'
}
},
casePages: {
decision: {
heroTitle: '投策智能体',
heroDesc: '面向企业投资决策的辅助智能体,整合多维度市场数据、行业趋势与政策信息,通过算法模拟不同决策场景的收益与风险,自动生成可视化分析报告。帮助企业快速梳理核心信息,预判市场走向,辅助降低决策偏差,提升投资方案的科学性与可行性',
tabs: { scenarios: '应用场景', solution: '解决方案', highlights: '项目亮点' },
scenariosTitle: '应用场景',
scenariosDesc: '覆盖企业投资决策全链路',
scenarios: [
{ title: '投资可行性研究', desc: '自动收集行业数据、市场趋势、政策信息,生成专业的投资可行性分析报告,辅助决策者快速评估项目价值与风险。' },
{ title: '市场调研分析', desc: '整合多维度市场数据,自动分析市场规模、竞争格局、发展趋势,生成详实的市场调研报告,支撑业务决策。' },
{ title: '竞品分析', desc: '自动收集竞品信息,分析产品特性、市场策略、用户反馈,生成竞品对比分析报告,帮助企业制定差异化竞争策略。' }
],
solutionTitle: '企业决策的困境与解决方案',
solutionDesc: '聚焦数据收集、研报撰写、知识管理、智能应用四大维度',
challengeTitle: '困境:数据丰富,洞察贫乏',
challenges: [
{ title: '数据孤岛严重', desc: '数据分散在不同业务系统中、或者网站信源中,难以打通整合,阻碍全面分析与决策。' },
{ title: '知识沉淀难', desc: '关键业务知识与专家经验主要存在于个人头脑中,随人员流动而流失。' },
{ title: '报告撰写耗时费力', desc: '手工整理数据、制作高质量决策报告过程繁琐,效率低下,难以快速响应需求。' }
],
abilityTitle: '解决方案E决策平台核心能力',
abilityDesc: '聚焦“数据收集、研报撰写、知识管理、智能应用”四大维度,帮助企业构建专属知识体系,赋能科学决策。',
abilities: [
{ title: '数据收集与整合', desc: '自动抓取内外部数据源,打破壁垒,统一数据口径' },
{ title: '知识管理与沉淀', desc: '将非结构化文档转化为结构化知识图谱,沉淀企业核心资产' },
{ title: '智能应用与问答', desc: '支持自然语言提问,快速检索与回答,即问即得关键洞察' },
{ title: 'AI辅助研报撰写', desc: '输入主题自动生成内容支持一键导出为PDF/PPT' }
],
highlightsTitle: '项目亮点',
highlightsDesc: '一次研究,双格式交付',
highlights: [
{ title: '一键生成PDF研究报告', desc: '在AI辅助生成研报内容后系统支持一键导出为格式规范、内容详实的PDF研究报告满足归档与深度阅读需求。' },
{ title: '一键生成PPT演示文稿', desc: '除了PDF系统还支持一键导出为PPT演示文稿并自动完成逻辑梳理、智能分页和专业排版即导即用。' }
],
ctaTitle: '开始使用投策智能体',
ctaDesc: '让AI赋能您的投资决策一次研究双格式交付',
contactSales: '联系销售'
},
contract: {
heroTitle: '合同智能审查',
heroDesc: '面向企业法务与业务签约全流程的专业审查智能体,聚合法规条文、企业内部风控标准、历史合同案例多维信息,依托大模型深度语义解析能力自动识别合同法律隐患,智能生成标准化修改建议与风险说明。',
tabs: { scenarios: '应用场景', solution: '解决方案', highlights: '项目亮点' },
scenariosTitle: '应用场景',
scenariosDesc: '覆盖企业合同全生命周期审核链路',
scenarios: [
{ title: '业务合同初审', desc: '自动解析购销、服务、租赁、合作类通用业务合同,逐条对标企业风控红线快速筛查风险点,输出初审意见,减轻法务基础审核工作量,快速完成业务前置审批。' },
{ title: '复杂商事合同深度风控', desc: '针对投融资、知识产权、工程、保密竞业等高风险专项合同,联动完整法条与司法判例开展多层级风险推演,梳理权责漏洞、违约缺陷、管辖争议等深层隐患,输出完整风险评估文档。' },
{ title: '多方合同版本比对修订', desc: '自动识别甲乙双方多轮修改稿件差异,区分新增、删减、修改条款,高亮标注风险变更内容,同步生成版本对比台账,辅助商务谈判与法务复核,避免改稿遗漏关键风险。' }
],
deleted: '删除',
added: '新增',
solutionTitle: '企业合同管理的困境与解决方案',
solutionDesc: '围绕数据归集、合同编审、知识沉淀、智能咨询四大核心维度',
challengeTitle: '现存困境',
challenges: [
{ title: '文件信息割裂分散', desc: '合同、法规、历史判例、内部模板散落在不同存储渠道,无统一检索入口,审核时需跨文件反复核对。' },
{ title: '风控经验难以留存复用', desc: '资深法务的审查要点、谈判底线、风险处置经验仅存于个人,人员交接后容易出现标准不统一。' },
{ title: '人工审核耗时长、标准化弱', desc: '海量合同逐条人工审阅消耗大量人力,不同法务审核尺度参差不齐,紧急签约场景响应慢。' }
],
abilityTitle: '解决方案',
abilities: [
{ title: '多源文件统一归集解析', desc: '批量上传PDF、Word、扫描件合同OCR识别图文内容统一结构化抽取交易主体、价款、履约、违约等关键信息。' },
{ title: '全条款AI智能编审修正', desc: '分层扫描合同全部条款,对标法律法规与企业内控规则标记高中低三级风险,配套标准化合规替换条款。' },
{ title: '法务知识库沉淀管理', desc: '将企业标准模板、审查清单、判例、内部风控制度转化为结构化知识库,沉淀企业专属法务资产。' },
{ title: '自然语言法务智能问答', desc: '支持业务、法务人员以口语化提问查询合规要求、条款写法、风险后果,即时输出专业解答与参考条款。' }
],
highlightsTitle: '项目亮点',
highlightsDesc: '全流程智能风控,四大核心审查能力落地',
highlights: [
{ title: '分级风险自动标注,配套合规整改条款', desc: '按重大、一般、提示三级划分风险,精准定位风险对应原文段落,每条风险同步匹配适配企业制度与现行法律的替换条款。' },
{ title: '多版本合同差异智能比对溯源', desc: '上传新旧合同、甲乙双方往来稿件,系统自动高亮新增、删减、变更条款,生成可追溯对比台账。' },
{ title: '全格式合同兼容识别,扫描件精准解析', desc: '支持Word、PDF、图片扫描件、盖章影像文件上传内置高精度OCR图文识别覆盖存量和增量合同文件。' },
{ title: '企业法务知识一键复用,审查标准统一', desc: '内置企业专属合同模板库、风控红线清单、行业判例库,新员工可直接复用成熟审查标准。' }
]
}
},
contactSales: {
title: '联系销售',
nameLabel: '1. 请填写您的姓名',
namePlaceholder: '请输入您的姓名',
phoneLabel: '2. 请填写您的联系方式',
phonePlaceholder: '请输入您的联系电话',
emailLabel: '3. 请填写您的邮箱',
emailPlaceholder: '请输入您的邮箱',
companyLabel: '4. 请填写您的公司名称',
companyPlaceholder: '请输入您的公司名称',
enterpriseLabel: '5. 请选择您的企业类型(单选)',
provinceLabel: '6. 请选择您所在的省份(单选)',
provincePlaceholder: '输入省份名称或拼音首字母搜索...',
messageLabel: '7. 如果您有其他问题需要咨询,请留言',
messagePlaceholder: '请输入您想咨询的内容...',
privacy: '您填写的信息仅用于本次业务对接沟通,公司将严格落实信息安全保护机制,不泄露、不滥用您的任何个人资料。',
phoneInvalid: '请输入正确的手机号',
emailInvalid: '请输入正确的邮箱地址',
enterpriseRequired: '请选择企业类型',
provinceRequired: '请选择所在省份',
privacyRequired: '请勾选同意协议后再提交!',
formInvalid: '请完善表单信息~',
cancel: '取消',
submit: '提交咨询',
qrcode: '扫码添加官方客服',
enterpriseOptions: {
largeEnterprise: '大型企业',
sme: '中小企业',
opcIndividual: 'OPC个人',
university: '高校科研机构',
government: '政府',
other: '其他'
}
},
yunbao: {
name: '云宝小助手',
online: '在线',
welcome: '嗨~ 我是云宝 👋<br>请问您想随便看看,还是直接聊聊需求?',
browse: '随便看看',
direct: '直接聊聊需求',
recommend: '好的~为您推荐我们的热门产品 👇',
moreProducts: '或者您还有其他想了解的产品吗?',
askProduct: '您想了解哪方面的产品或服务呢?',
learnMore: '查看更多→',
submit: '提交咨询',
consultantNote: '请留下您的联系方式,我们的顾问将尽快与您联系 😊',
infoNote: '信息仅用于顾问联系',
products: {
bid: 'E投标',
tender: 'E招标',
evaluation: 'E评标',
loggingReview: '采伐智审',
gasMonitor: '燃机智慧监盘',
powerPrice: '电价预测',
comic: 'AI漫剧制作',
contract: '合同智能审查',
decision: '投策智能体'
},
productDescs: {
bid: '更智能的标书写作引擎',
contract: 'AI驱动合同风险审查效率提升60%+',
decision: '分钟级投研分析,精准辅助投资决策'
},
productIntroDefault: '这是一款优秀的AI产品欢迎进一步了解',
nameRequired: '请先填写姓名和联系电话哦~',
phoneInvalid: '请输入正确的 11 位手机号哦~',
submitted: '已提交联系方式',
consultingContent: '我想咨询关于【{product}】的产品信息',
defaultContent: '云宝对话咨询',
submitting: '提交中...',
success: '收到!我们的顾问将尽快与您联系 🎉<br>感谢您的信任!',
submitFail: '提交失败了,您可以稍后重试。',
networkFail: '网络开小差了,提交失败,您可以重试一次。',
retry: '重新提交',
openedContract: '已为您打开合同智能审查页面 📄<br>还有其他想了解的吗?',
openedDecision: '已为您打开投策智能体页面 📊<br>还有其他想了解的吗?',
openedPage: '已为您打开相关页面。还有其他想了解的吗?'
},
...autoMessages
}

View File

@ -11,7 +11,7 @@ import {getHomePath} from "@/views/setting/tools";
NProgress.configure({showSpinner: false}); // NProgress Configuration
const whiteList = ["product", "/tokenMarket", "/modelDetail", "/modelApiDocument", "/login", "/homePage", "/registrationPage", "/shoppingCart", "/homePageImage","/h5HomePage",'/H5about','/modelProductDetail','/ncmatchHome']; // no redirect whitelist
const whiteList = ["product", "/tokenMarket", "/modelDetail", "/modelApiDocument", "/login", "/homePage", "/registrationPage", "/shoppingCart", "/homePageImage","/h5HomePage",'/H5about','/modelProductDetail','/ncmatchHome', '/agreement']; // no redirect whitelist
// 获取用户代理字符串
const userAgent = window.navigator.userAgent;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
export function isEnglishLocale(i18n) {
return !!(i18n && i18n.locale === 'en-US')
}
export function getDictLabel(item, isEn) {
if (!item) return ''
if (isEn) {
return item.dict_value_en || item.dict_value_zh || item.dict_value || ''
}
return item.dict_value_zh || item.dict_value || item.dict_value_en || ''
}
export function extractConsultOptionList(res) {
if (res && Array.isArray(res.data)) return res.data
if (res && res.data && Array.isArray(res.data.data)) return res.data.data
return []
}
export function normalizeDictOptions(list, type) {
return list
.filter(item => item && item.dict_type === type)
.sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0))
.map(item => ({
id: String(item.dict_key),
nameZh: item.dict_value_zh || item.dict_value || '',
nameEn: item.dict_value_en || item.dict_value_zh || item.dict_value || ''
}))
}
export function parseDirectionParts(label, isEn) {
if (!label) {
return { title: '', desc: '' }
}
const text = String(label)
if (isEn) {
const match = text.match(/^(.+?)\s*\((.+)\)\s*$/)
return match
? { title: match[1].trim(), desc: match[2].trim() }
: { title: text, desc: '' }
}
const match = text.match(/^(.+?)(.+?)$/)
return match
? { title: match[1].trim(), desc: match[2].trim() }
: { title: text, desc: '' }
}
export function normalizeDirectionOptions(list) {
return list
.filter(item => item && item.dict_type === 'direction')
.sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0))
.map(item => {
const nameZh = item.dict_value_zh || item.dict_value || ''
const nameEn = item.dict_value_en || nameZh
const parts = parseDirectionParts(nameZh, false)
return {
id: String(item.dict_key),
nameZh,
nameEn,
titleZh: parts.title,
descZh: parts.desc,
titleEn: parseDirectionParts(nameEn, true).title,
descEn: parseDirectionParts(nameEn, true).desc
}
})
}
export function localizeDictOptions(options, isEn) {
return (options || []).map(item => ({
...item,
name: isEn ? item.nameEn : item.nameZh
}))
}
export function localizeDirectionOptions(options, isEn) {
return (options || []).map(item => ({
...item,
name: isEn ? item.nameEn : item.nameZh,
title: isEn ? item.titleEn : item.titleZh,
desc: isEn ? item.descEn : item.descZh
}))
}

View File

@ -63,7 +63,7 @@
<el-form-item label="5. 请选择您的企业类型(单选)" prop="enterprise_type">
<el-radio-group v-model="formData.enterprise_type" class="option-grid">
<el-radio
v-for="item in enterpriseOptions"
v-for="item in localizedEnterpriseOptions"
:key="item.id"
:label="String(item.id)"
class="option-item"
@ -82,7 +82,7 @@
class="full-select"
>
<el-option
v-for="item in provinceOptions"
v-for="item in localizedProvinceOptions"
:key="`region-${item.id}-${item.name}`"
:label="item.name"
:value="String(item.id)"
@ -93,7 +93,7 @@
<el-form-item label="7. 您想咨询的方向(可多选)">
<el-checkbox-group v-model="formData.consult_direction_list" class="direction-list">
<el-checkbox
v-for="item in consultDirectionOptions"
v-for="item in localizedConsultDirectionOptions"
:key="item.id"
:label="item.id"
class="direction-item"
@ -141,6 +141,14 @@
<script>
import { reqConsultForm, reqProductConsult } from '@/api/H5'
import {
extractConsultOptionList,
isEnglishLocale,
localizeDictOptions,
localizeDirectionOptions,
normalizeDictOptions as buildDictOptions,
normalizeDirectionOptions as buildDirectionOptions
} from '@/utils/consultDict'
export default {
name: 'MobileFullScreenConsultDialog',
@ -207,9 +215,21 @@ export default {
set(value) {
this.$emit('update:visible', value)
}
},
localizedEnterpriseOptions() {
return localizeDictOptions(this.enterpriseOptions, isEnglishLocale(this.$i18n))
},
localizedProvinceOptions() {
return localizeDictOptions(this.provinceOptions, isEnglishLocale(this.$i18n))
},
localizedConsultDirectionOptions() {
return localizeDirectionOptions(this.consultDirectionOptions, isEnglishLocale(this.$i18n))
}
},
watch: {
'$i18n.locale'() {
this.provinceSelectKey += 1
},
visible: {
immediate: true,
handler(newVal) {
@ -256,44 +276,15 @@ export default {
this.dialogVisible = false
this.$emit('close')
},
normalizeDictOptions(list, type) {
return list
.filter(item => item && item.dict_type === type)
.sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0))
.map(item => ({
id: String(item.dict_key),
name: item.dict_value
}))
},
normalizeDirectionOptions(list) {
return list
.filter(item => item && item.dict_type === 'direction')
.sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0))
.map(item => {
const value = item.dict_value || ''
const match = value.match(/^(.+?)(.+?)$/)
return {
id: String(item.dict_key),
name: value,
title: match ? match[1] : value,
desc: match ? match[2] : ''
}
})
},
extractConsultOptionList(res) {
if (res && Array.isArray(res.data)) return res.data
if (res && res.data && Array.isArray(res.data.data)) return res.data.data
return []
},
async fetchConsultOptions() {
try {
const res = await reqConsultForm()
const list = this.extractConsultOptionList(res)
const list = extractConsultOptionList(res)
if (!list.length) return
const enterpriseOptions = this.normalizeDictOptions(list, 'enterprise_type')
const provinceOptions = this.normalizeDictOptions(list, 'region')
const consultDirectionOptions = this.normalizeDirectionOptions(list)
const enterpriseOptions = buildDictOptions(list, 'enterprise_type')
const provinceOptions = buildDictOptions(list, 'region')
const consultDirectionOptions = buildDirectionOptions(list)
if (enterpriseOptions.length) this.enterpriseOptions = enterpriseOptions
if (provinceOptions.length) {

View File

@ -11,7 +11,7 @@
>
<div class="login-card">
<div class="brand-area">
<div class="brand-text">
<h2>{{ activeTab === 'login' ? '欢迎登录' : '创建账号' }}</h2>
</div>
@ -41,7 +41,7 @@
prefix-icon="el-icon-lock"
@keyup.enter.native="handleLogin"
>
<i slot="suffix" class="el-icon-view password-eye" @click="loginPwdVisible = !loginPwdVisible"></i>
<i slot="suffix" class="el-icon-view password-eye" @click="loginPwdVisible = !loginPwdVisible" />
</el-input>
</el-form-item>
</template>
@ -93,14 +93,18 @@
prefix-icon="el-icon-lock"
@keyup.enter.native="handleRegister"
>
<i slot="suffix" class="el-icon-view password-eye" @click="regPwdVisible = !regPwdVisible"></i>
<i slot="suffix" class="el-icon-view password-eye" @click="regPwdVisible = !regPwdVisible" />
</el-input>
</el-form-item>
</el-form>
<div class="agreement-wrap">
<el-checkbox v-model="registerForm.agree">
我已阅读并同意用户协议隐私政策产品服务协议
我已阅读并同意
<a class="agreement-link" :href="getAgreementUrl('user')" target="_blank" rel="noopener noreferrer" @click.stop>用户协议</a>
<a class="agreement-link" :href="getAgreementUrl('privacy')" target="_blank" rel="noopener noreferrer" @click.stop>隐私政策</a>
</el-checkbox>
</div>
@ -234,6 +238,9 @@ export default {
if (this.$refs.loginForm) this.$refs.loginForm.clearValidate()
})
},
getAgreementUrl(type) {
return `${window.location.origin}/#/agreement/${type}`
},
passwordEncryption(passwordUser) {
const publicKey = '-----BEGIN PUBLIC KEY-----\n' +
'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApJ3ThUWT3CgvH0O8rrT6\n' +
@ -785,6 +792,21 @@ export default {
}
}
.agreement-link {
padding: 0;
color: #1d4ed8;
font-size: inherit;
line-height: inherit;
background: transparent;
border: 0;
cursor: pointer;
}
.agreement-link:hover {
color: #0f172a;
text-decoration: underline;
}
.bottom-link {
display: block;
width: 100%;
@ -836,4 +858,3 @@ export default {
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
<template>
<div class="contract-case-page">
<div class="decor decor--blue"></div>
<div class="decor decor--purple"></div>
<div class="decor decor--blue" />
<div class="decor decor--purple" />
<section class="case-hero" :style="{ backgroundImage: `url(${bannerImg})` }">
<div class="case-container">
<div class="case-hero__content">
<h1>合同智能审查</h1>
<h1>{{ $t('casePages.contract.heroTitle') }}</h1>
<p>
面向企业法务与业务签约全流程的专业审查智能体聚合法规条文企业内部风控标准历史合同案例多维信息依托大模型深度语义解析能力自动识别合同法律隐患智能生成标准化修改建议与风险说明
{{ $t('casePages.contract.heroDesc') }}
</p>
</div>
</div>
@ -17,7 +17,7 @@
<section class="case-tabs">
<div class="case-container">
<button
v-for="tab in tabs"
v-for="tab in localizedTabs"
:key="tab.id"
type="button"
class="tab-item"
@ -33,8 +33,8 @@
<section id="scenarios" class="case-section">
<div class="case-container">
<div class="section-heading">
<h2>应用场景</h2>
<p>覆盖企业合同全生命周期审核链路</p>
<h2>{{ $t('casePages.contract.scenariosTitle') }}</h2>
<p>{{ $t('casePages.contract.scenariosDesc') }}</p>
</div>
<div class="case-scenario-grid">
<article class="case-feature-card scenario-card">
@ -75,9 +75,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414A1 1 0 0119 9.414V19a2 2 0 01-2 2z" />
</svg>
</span>
<h3>业务合同初审</h3>
<h3>{{ $t('casePages.contract.scenarios.0.title') }}</h3>
</div>
<p>自动解析购销服务租赁合作类通用业务合同逐条对标企业风控红线快速筛查风险点输出初审意见减轻法务基础审核工作量快速完成业务前置审批</p>
<p>{{ $t('casePages.contract.scenarios.0.desc') }}</p>
</article>
<article class="case-feature-card scenario-card">
@ -109,9 +109,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
</span>
<h3>复杂商事合同深度风控</h3>
<h3>{{ $t('casePages.contract.scenarios.1.title') }}</h3>
</div>
<p>针对投融资知识产权工程保密竞业等高风险专项合同联动完整法条与司法判例开展多层级风险推演梳理权责漏洞违约缺陷管辖争议等深层隐患输出完整风控评估文档</p>
<p>{{ $t('casePages.contract.scenarios.1.desc') }}</p>
</article>
<article class="case-feature-card scenario-card">
@ -144,9 +144,9 @@
</g>
<g class="diff-tags">
<rect x="90" y="48" width="30" height="8" rx="2" fill="#ef4444" opacity="0.2" />
<text x="95" y="54" font-size="8" fill="#ef4444" font-weight="bold">删除</text>
<text x="95" y="54" font-size="8" fill="#ef4444" font-weight="bold">{{ $t('casePages.contract.deleted') || '删除' }}</text>
<rect x="230" y="63" width="30" height="8" rx="2" fill="#10b981" opacity="0.2" />
<text x="235" y="69" font-size="8" fill="#10b981" font-weight="bold">新增</text>
<text x="235" y="69" font-size="8" fill="#10b981" font-weight="bold">{{ $t('casePages.contract.added') || '新增' }}</text>
</g>
</svg>
</div>
@ -156,9 +156,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4" />
</svg>
</span>
<h3>多方合同版本比对修订</h3>
<h3>{{ $t('casePages.contract.scenarios.2.title') }}</h3>
</div>
<p>自动识别甲乙双方多轮修改稿件差异区分新增删减修改条款高亮标注风险变更内容同步生成版本对比台账辅助商务谈判与法务复核避免改稿遗漏关键风险</p>
<p>{{ $t('casePages.contract.scenarios.2.desc') }}</p>
</article>
</div>
</div>
@ -167,8 +167,8 @@
<section id="solution" class="case-section solution-section">
<div class="case-container">
<div class="section-heading">
<h2>企业合同管理的困境与解决方案</h2>
<p>围绕数据归集合同编审知识沉淀智能咨询四大核心维度</p>
<h2>{{ $t('casePages.contract.solutionTitle') }}</h2>
<p>{{ $t('casePages.contract.solutionDesc') }}</p>
</div>
<div class="solution-grid">
<div class="solution-column">
@ -178,9 +178,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M4.93 19h14.14c1.54 0 2.5-1.67 1.73-3L13.73 4c-.77-1.33-2.69-1.33-3.46 0L3.2 16c-.77 1.33.19 3 1.73 3z" />
</svg>
</span>
<h3>现存困境</h3>
<h3>{{ $t('casePages.contract.challengeTitle') }}</h3>
</div>
<article v-for="item in problems" :key="item.title" class="solution-item solution-item--danger">
<article v-for="item in localizedProblems" :key="item.title" class="solution-item solution-item--danger">
<span class="solution-icon">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="item.icon" />
@ -200,9 +200,9 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
<h3>解决方案</h3>
<h3>{{ $t('casePages.contract.abilityTitle') }}</h3>
</div>
<article v-for="item in solutions" :key="item.title" class="solution-item solution-item--primary">
<article v-for="item in localizedSolutions" :key="item.title" class="solution-item solution-item--primary">
<span class="solution-icon">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="item.icon" />
@ -221,11 +221,11 @@
<section id="highlights" class="case-section">
<div class="case-container">
<div class="section-heading">
<h2>项目亮点</h2>
<p>全流程智能风控四大核心审查能力落地</p>
<h2>{{ $t('casePages.contract.highlightsTitle') }}</h2>
<p>{{ $t('casePages.contract.highlightsDesc') }}</p>
</div>
<div class="case-highlight-grid">
<article v-for="(item, index) in highlights" :key="item.title" class="case-highlight-card">
<article v-for="(item, index) in localizedHighlights" :key="item.title" class="case-highlight-card">
<span class="highlight-num">{{ index + 1 }}</span>
<div>
<h3>{{ item.title }}</h3>
@ -331,6 +331,23 @@ export default {
]
}
},
computed: {
localizedTabs() {
return this.tabs.map(tab => ({
...tab,
label: this.$t(`casePages.contract.tabs.${tab.id}`)
}))
},
localizedProblems() {
return this.getLocalizedList(this.problems, 'casePages.contract.challenges')
},
localizedSolutions() {
return this.getLocalizedList(this.solutions, 'casePages.contract.abilities')
},
localizedHighlights() {
return this.getLocalizedList(this.highlights, 'casePages.contract.highlights')
}
},
mounted() {
this.$nextTick(() => {
const scroller = this.getScrollContainer()
@ -343,6 +360,13 @@ export default {
this.getScrollContainer().removeEventListener('scroll', this.handlePageScroll)
},
methods: {
getLocalizedList(list, keyPrefix) {
return list.map((item, index) => ({
...item,
title: this.$t(`${keyPrefix}.${index}.title`),
desc: this.$t(`${keyPrefix}.${index}.desc`)
}))
},
getScrollContainer() {
return document.getElementById('homeOut') || window
},

View File

@ -1,17 +1,17 @@
<template>
<div class="decision-case-page">
<div class="decor decor--blue"></div>
<div class="decor decor--purple"></div>
<div class="decor decor--deep-blue"></div>
<div class="decor decor--deep-purple"></div>
<div class="decor decor--blue" />
<div class="decor decor--purple" />
<div class="decor decor--deep-blue" />
<div class="decor decor--deep-purple" />
<section class="case-hero">
<img class="case-hero__bg" :src="bannerImg" alt="">
<div class="case-container">
<div class="case-hero__content">
<h1>投策智能体</h1>
<h1>{{ $t('casePages.decision.heroTitle') }}</h1>
<p>
面向企业投资决策的辅助智能体整合多维度市场数据行业趋势与政策信息通过算法模拟不同决策场景的收益与风险自动生成可视化分析报告帮助企业快速梳理核心信息预判市场走向辅助降低决策偏差提升投资方案的科学性与可行性
{{ $t('casePages.decision.heroDesc') }}
</p>
</div>
</div>
@ -20,7 +20,7 @@
<section class="case-tabs">
<div class="case-container">
<button
v-for="tab in tabs"
v-for="tab in localizedTabs"
:key="tab.id"
type="button"
class="tab-item"
@ -36,11 +36,11 @@
<section id="scenarios" class="case-section">
<div class="case-container">
<div class="section-heading">
<h2>应用场景</h2>
<p>覆盖企业投资决策全链路</p>
<h2>{{ $t('casePages.decision.scenariosTitle') }}</h2>
<p>{{ $t('casePages.decision.scenariosDesc') }}</p>
</div>
<div class="scenario-grid">
<article v-for="item in scenarios" :key="item.title" class="feature-card">
<article v-for="item in localizedScenarios" :key="item.title" class="feature-card">
<div class="feature-card__head">
<div class="icon-gradient">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -58,8 +58,8 @@
<section id="solution" class="case-section">
<div class="case-container">
<div class="section-heading">
<h2>企业决策的困境与解决方案</h2>
<p>聚焦数据收集研报撰写知识管理智能应用四大维度</p>
<h2>{{ $t('casePages.decision.solutionTitle') }}</h2>
<p>{{ $t('casePages.decision.solutionDesc') }}</p>
</div>
<div class="solution-grid">
<article class="problem-card">
@ -67,10 +67,10 @@
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
困境数据丰富洞察贫乏
{{ $t('casePages.decision.challengeTitle') }}
</h3>
<div class="list-block">
<div v-for="item in problems" :key="item.title" class="list-item list-item--danger">
<div v-for="item in localizedProblems" :key="item.title" class="list-item list-item--danger">
<div class="list-icon">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="item.icon" />
@ -89,13 +89,13 @@
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
解决方案E决策平台核心能力
{{ $t('casePages.decision.abilityTitle') }}
</h3>
<p class="solution-card__intro">
聚焦数据收集研报撰写知识管理智能应用四大维度帮助企业构建专属知识体系赋能科学决策
{{ $t('casePages.decision.abilityDesc') }}
</p>
<div class="ability-list">
<div v-for="item in abilities" :key="item.title" class="ability-item">
<div v-for="item in localizedAbilities" :key="item.title" class="ability-item">
<div class="ability-icon icon-gradient">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="item.icon" />
@ -115,11 +115,11 @@
<section id="highlights" class="case-section">
<div class="case-container">
<div class="section-heading">
<h2>项目亮点</h2>
<p>一次研究双格式交付</p>
<h2>{{ $t('casePages.decision.highlightsTitle') }}</h2>
<p>{{ $t('casePages.decision.highlightsDesc') }}</p>
</div>
<div class="highlight-grid">
<article v-for="item in highlights" :key="item.title" class="feature-card">
<article v-for="item in localizedHighlights" :key="item.title" class="feature-card">
<div class="feature-card__head">
<div class="icon-gradient">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
@ -137,13 +137,13 @@
<section class="case-cta">
<div class="case-container case-cta__inner">
<h2>开始使用投策智能体</h2>
<p>让AI赋能您的投资决策一次研究双格式交付</p>
<button type="button" @click="handleContact">联系销售</button>
<h2>{{ $t('casePages.decision.ctaTitle') }}</h2>
<p>{{ $t('casePages.decision.ctaDesc') }}</p>
<button type="button" @click="handleContact">{{ $t('casePages.decision.contactSales') }}</button>
</div>
</section>
<Talk></Talk>
<Talk />
</div>
</template>
@ -232,6 +232,26 @@ export default {
bannerImg: require('./img.jpg')
}
},
computed: {
localizedTabs() {
return this.tabs.map(tab => ({
...tab,
label: this.$t(`casePages.decision.tabs.${tab.id}`)
}))
},
localizedScenarios() {
return this.getLocalizedList(this.scenarios, 'casePages.decision.scenarios')
},
localizedProblems() {
return this.getLocalizedList(this.problems, 'casePages.decision.challenges')
},
localizedAbilities() {
return this.getLocalizedList(this.abilities, 'casePages.decision.abilities')
},
localizedHighlights() {
return this.getLocalizedList(this.highlights, 'casePages.decision.highlights')
}
},
mounted() {
this.$nextTick(() => {
const scroller = this.getScrollContainer()
@ -244,6 +264,13 @@ export default {
this.getScrollContainer().removeEventListener('scroll', this.handlePageScroll)
},
methods: {
getLocalizedList(list, keyPrefix) {
return list.map((item, index) => ({
...item,
title: this.$t(`${keyPrefix}.${index}.title`),
desc: this.$t(`${keyPrefix}.${index}.desc`)
}))
},
getScrollContainer() {
return document.getElementById('homeOut') || window
},

View File

@ -0,0 +1,103 @@
<template>
<main class="agreement-preview-page">
<section class="agreement-preview-card">
<article class="agreement-content">
<p
v-for="(paragraph, index) in currentDoc.paragraphs"
:key="`${paragraph.slice(0, 12)}-${index}`"
class="agreement-paragraph"
:class="{
'agreement-paragraph--heading': isHeadingParagraph(paragraph),
'agreement-paragraph--sub': isSubParagraph(paragraph)
}"
v-html="paragraph"
/>
</article>
</section>
</main>
</template>
<script>
import docs from './agreementDocs'
export default {
name: 'AgreementPreview',
computed: {
currentDoc() {
return docs[this.$route.params.type] || docs.user
}
},
methods: {
isHeadingParagraph(paragraph) {
return /^<strong>[^<]+<\/strong>$/.test(String(paragraph || '').trim())
},
isSubParagraph(paragraph) {
const text = String(paragraph || '').trim()
return /^(?:\d+\.\d+\.|\d+\.\s|[0-9]+\.\s)/.test(text.replace(/<[^>]+>/g, ''))
}
}
}
</script>
<style scoped lang="scss">
.agreement-preview-page {
height: 100vh;
min-height: 100vh;
padding: 48px 24px 64px;
overflow-y: auto;
color: #111827;
background: #fff;
box-sizing: border-box;
}
.agreement-preview-card {
width: min(920px, 100%);
margin: 0 auto;
padding: 0;
}
.agreement-content {
color: #374151;
font-size: 15px;
line-height: 1.9;
}
.agreement-content p {
margin: 0 0 14px;
white-space: pre-wrap;
}
.agreement-content p.agreement-paragraph--heading {
margin-top: 6px;
margin-bottom: 10px;
color: #0f172a;
font-weight: 700;
}
.agreement-content p.agreement-paragraph--sub {
padding-left: 1.25em;
margin-bottom: 10px;
}
::v-deep .agreement-content strong {
color: #0f172a;
font-weight: 700;
}
.agreement-content p:first-child {
color: #0f172a;
font-size: 20px;
font-weight: 800;
}
.agreement-content p:first-child ::v-deep strong {
font-size: inherit;
font-weight: inherit;
}
@media (max-width: 640px) {
.agreement-preview-page {
padding: 28px 16px 36px;
}
}
</style>

View File

@ -0,0 +1,147 @@
export default {
'user': {
'title': '用户协议',
'paragraphs': [
'<strong>开元云用户协议</strong>',
'更新日期【2026】年【7】月【30】日',
'生效日期【2026】年【7】月【30】日',
'本《开元云用户协议》(以下简称“本协议”)由开元云(北京)科技有限公司(以下简称“开元云”或“我们”)与注册、访问或使用开元云服务的自然人、法人或非法人组织(以下简称“用户”或“您”)订立。',
'<strong>请您在注册、下单或使用服务前完整阅读本协议。与责任限制、费用、服务暂停或终止、数据处理及争议解决有关的条款已采用加粗方式提示。您点击同意、提交订单、开通或实际使用服务,均表示您已阅读并同意本协议。您代表法人或其他组织操作的,应保证已取得充分授权。</strong>',
'<strong>1. 协议范围与定义</strong>',
'1.1. 开元云平台,是指由开元云运营的网站、业务平台、客户端、控制台、应用程序、接口及其他服务载体,包括开元算力应用服务平台及后续更名、升级或新增的服务载体。',
'1.2. 开元云服务,是指开元云通过平台或双方确认的订单提供的云计算、算力、算力网络、人工智能及相关产品和技术服务,具体以产品页面、订单或服务说明为准。',
'1.3. 开元云既可能直接提供服务,也可能代理销售、转售或协助交付第三方服务。实际销售方、服务提供方、开票方及售后责任方,以订单记载为准。',
'1.4. 订单,是指用户通过平台提交并由系统确认的订单,以及双方签署或确认的报价单、采购单、服务单、工作说明书或其他交易文件。订单应列明或能够确定服务内容、服务期限、计费方式、实际销售方或服务提供方、开票方、售后责任方及适用的服务规则。',
'1.5. 本协议与订单、产品说明、服务等级协议、隐私政策及适用的平台规则共同构成双方协议。约定不一致时,按双方专项书面约定、订单、产品专项规则、本协议的顺序适用;法律另有规定的除外。',
'<strong>2. 账户注册与管理</strong>',
'2.1. 您应按要求提供真实、准确、完整、有效的注册及认证信息,并在信息变化后及时更新。特定服务依法需要实名核验、资质审查或安全评估的,您应予配合。',
'2.2. 您应妥善保管账户及认证信息,并合理设置操作权限。通过您账户实施的操作原则上视为您的行为,但您能够证明账户被未经授权使用且已及时采取合理措施的除外。',
'2.3. 发现账户或认证信息被盗用、泄露或存在异常操作时,您应及时通知开元云并采取必要措施。开元云可根据风险采取身份复核、限制登录或临时冻结等措施。',
'2.4. 未经开元云同意,您不得转让、出租、出借账户,或者以共享账户等方式规避计费、资质审查或访问控制。',
'<strong>3. 服务订购与交付</strong>',
'3.1. 服务内容、期限、费用、交付方式、技术指标及支持标准,以产品页面、订单或双方书面约定为准。您应在下单前核对相关信息。',
'3.2. 平台展示内容符合要约条件且订单提交成功的,订单成立;订单明确需经资源、资质或合规审核的,以开元云确认、服务开通或双方签署书面文件时成立。',
'3.3. 对开元云直接提供的服务,开元云按约承担交付、维护及售后责任。对第三方服务,各方责任依订单及订购前向您提供的第三方规则确定。<strong>开元云的代理或平台角色不免除其依法应承担的信息披露、平台管理及因自身过错产生的责任。</strong>',
'3.4. 服务可通过账户开通、资源交付、接口启用、部署完成或订单约定的方式交付。需要验收的,按订单约定办理;订单未约定验收期限的,您应在收到交付通知后五个工作日内完成合理核验并反馈问题,隐蔽缺陷不受该期限限制。',
'3.5. 服务变更、扩容、迁移或定制开发,应通过订单、变更单或双方书面确认实施。',
'<strong>4. 订购、交付与验收</strong>',
'4.1. 您应在下单前核对服务名称、配置、数量、价格、第三方服务商及限制等条件。平台提供订单更正和取消入口的,您可在订单确认前修改;订单确认后的变更、退订或迁移按对应产品规则或双方约定办理。',
'4.2. 平台展示的信息符合要约条件且用户提交订单成功的,订单成立;平台明确为要约邀请,或订单需经资源、资质、信用或合规审核的,以开元云确认、资源开通或双方签署书面文件时成立。开元云不得以格式条款约定用户付款后合同仍不成立。',
'4.3. 服务通过账户开通、资源交付、许可码发送、接口启用、部署完成或订单约定的其他方式交付。需要验收的,验收标准和期限以订单为准;订单未约定的,用户应在收到交付通知后五个工作日内完成合理核验并反馈可复现的问题,不影响用户依法就隐蔽缺陷主张权利。',
'4.4. 按周期续费的服务,以订单是否设置自动续费为准。开元云在自动扣款前应以合理方式提示扣款金额和时间,并提供便捷的取消方式;用户取消后不再产生下一周期费用,但已生效周期按约定继续履行。',
'4.5. 资源扩容、迁移、版本升级、服务内容变更或定制开发,应通过新订单、变更单或双方书面确认实施。未经确认的口头沟通不构成对服务范围、费用或期限的变更。',
'<strong>5. 费用、支付、发票与退款</strong>',
'<strong>5.1. 您应按照订单约定的价格、计费单位、结算周期和支付期限付款。因用户使用量、配置或调用次数变化产生的费用,以平台计量记录和订单计费规则为准;用户对计量结果有异议的,应在账单出具后十五日内提出,开元云应提供合理的核验渠道。</strong>',
'5.2. 除订单另有约定,价格不含因用户自身支付方式产生的银行手续费或其他第三方费用。开元云调整服务价格的,应在调整生效前通过平台公告、站内信、电子邮件或订单页面通知;已生效的固定期限订单不受影响,按量服务和续费周期自通知载明的日期适用新价格。',
'5.3. 发票由订单或结算页面列明的开票主体依法开具。您应提供真实、准确的开票信息;因信息错误造成的重开、红冲或邮寄成本,由责任方承担。',
'<strong>5.4. 退订、退款及未消费余额的处理,以订单和对应产品规则为准。涉及第三方服务的,还受第三方服务商的退订条件和资源采购规则约束。</strong>',
'5.5. 用户逾期付款的,开元云可催告并给予合理补救期限;用户在期限届满后仍未付款的,开元云可暂停相应服务并按订单约定收取违约金。暂停前,开元云应在合理可行范围内提示用户备份或迁移数据;紧急安全风险、恶意欠费或法律要求立即暂停的除外。',
'<strong>6. 用户数据与个人信息</strong>',
'6.1. 用户对其通过服务上传、生成、存储或处理的数据和内容(以下简称“用户数据”)依法享有相应权利。除履行协议、维护安全、遵守法律或取得用户授权外,开元云不取得用户数据的所有权,也不将其用于与提供服务无关的目的。',
'6.2. 开元云为账户管理、交易结算、客户服务、安全保障及依法运营而处理个人信息的,按照《开元云隐私政策》执行。',
'6.3. 用户决定个人信息处理目的和方式、开元云仅按用户指示提供处理能力的,用户应保证具有合法处理依据;开元云应按照约定和用户的合法指示处理,并采取与风险相适应的安全措施。必要时,双方可另行签署数据处理协议。',
'<strong>6.4. 为履行订单确需委托第三方处理或向第三方提供用户数据的,开元云应依法履行告知、合同约束及安全管理义务。未经合法依据,不得向无关第三方提供用户个人信息。</strong>',
'6.5. 涉及数据跨境的,由依法负有责任的一方完成相应合规程序。开元云不得在未告知用户的情况下擅自改变订单约定的数据存储地域。',
'6.6. 开元云应采取必要的网络和数据安全措施。发生可能影响用户权益的安全事件时,应及时采取补救措施,并按法律规定和合同约定履行通知、报告义务。',
'6.7. 服务终止后,开元云按照订单、产品规则或数据处理协议提供合理的数据导出期限,并在期限届满后依法删除或匿名化处理用户数据;依法需要留存的除外。',
'<strong>7. 知识产权</strong>',
'7.1. 开元云平台、软件、接口、文档、商标及相关技术成果的知识产权归开元云或相应权利人所有。未经许可,用户不得超出订单及产品规则约定的范围使用。',
'7.2. 服务期限内,用户获得仅限自身合法业务使用的、非独占且不可转让的使用权。第三方产品或开源组件适用其各自许可条款。',
'7.3. 用户数据及用户自行开发成果的权利,依法或依双方约定确定。用户授权开元云在提供和保障服务所必需的范围内处理用户数据。<strong>未经用户另行明确授权,开元云不得使用用户的非公开业务数据训练面向不特定用户的通用模型。</strong>',
'7.4. 人工智能或模型服务的输出可能存在不准确或权利瑕疵。用户应结合使用场景进行核验,并依法处理输出内容的使用及权利风险。',
'<strong>8. 服务运行与变更</strong>',
'8.1. 开元云按照订单或服务等级协议维护其直接提供的服务。第三方服务的可用性、维护及补偿标准,以订单和第三方规则为准;开元云作出更高承诺的,从其承诺。',
'8.2. 因维护升级需要计划中断服务的,开元云应按约提前通知;遇有安全事件、重大故障或主管机关要求等紧急情况,可先行处置并及时通知。',
'8.3. 开元云可以对服务进行合理升级或调整。涉及主要功能、关键技术指标、数据处理方式或费用的重大变化,应提前合理通知;变化实质影响合同目的的,用户可依法解除受影响的服务。',
'8.4. 第三方停止或变更服务导致迁移、替换或退订的,开元云应及时通知并提供合理处理方案。费用和责任按照订单、第三方规则及各方过错确定。',
'<strong>9. 服务暂停与终止</strong>',
'9.1. 用户可按订单和产品规则申请退订或停止续费。固定期限服务到期且未续费的,服务终止。',
'<strong>9.2. 用户逾期付款、严重违反本协议、造成现实安全风险,或者依法需要暂停服务的,开元云可根据风险限制或暂停相关服务。除紧急情形外,开元云应事先通知并给予合理补救期限。</strong>',
'9.3. 一方严重违约且在合理期限内未改正的,守约方可解除受影响的订单;违约无法补救或导致重大安全风险的,可立即解除。',
'9.4. 服务终止不影响终止前已经产生的付款、保密、数据处理、责任承担及争议解决义务。用户数据按照第6.7条处理。',
'<strong>10. 保证、免责与责任限制</strong>',
'10.1. 开元云应以符合行业合理标准的技术和管理措施提供服务。除订单、产品说明或法律另有规定外,开元云不保证服务适合用户的特定目的或实现特定结果。',
'<strong>10.2. 人工智能、模型、智能分析及计算结果可能存在错误、遗漏或偏差,仅供辅助使用,不能替代专业审查、验证或依法应由人工作出的决定。本条不免除开元云因虚假宣传、违反明示承诺或自身过错依法应承担的责任。</strong>',
'10.3. 因用户自身原因或不属于开元云控制范围的第三方原因造成的损失,由责任方依法承担;开元云对其自身过错承担相应责任。',
'<strong>10.4. 在法律允许的范围内,一方仅对其违约或过错造成的直接且可合理预见的损失承担责任。除法律规定不得限制的责任以及开元云故意、重大过失外,开元云就单一订单承担的累计赔偿责任,以索赔事件发生前十二个月内用户就该订单项下受影响服务实际支付的费用总额为上限;订单另有约定的,从其约定。</strong>',
'10.5. 本协议的免责或限责条款不适用于法律禁止免责或限制责任的情形,也不影响消费者依法享有的权利。',
'<strong>11. 保密</strong>',
'11.1. 一方因订立或履行本协议知悉的对方非公开技术、经营、数据及其他依其性质应属保密的信息,均为保密信息。接收方仅可为履行本协议使用,并应采取合理保护措施。',
'11.2. 已经合法公开、从无保密义务的第三方合法取得、接收方能够证明独立取得,或披露方同意公开的信息,不受前款限制。依法应披露的,接收方可在法定范围内披露,并在法律允许时通知披露方。',
'11.3. 保密义务在协议终止后持续五年;商业秘密、个人信息及重要数据依法律规定持续保护。',
'<strong>12. 不可抗力与通知</strong>',
'12.1. 因不能预见、不能避免且不能克服的事件导致不能履行的,受影响方在法律允许范围内部分或全部免责,但迟延履行后发生不可抗力的除外。受影响方应及时通知并采取合理减损措施。',
'12.2. 不可抗力持续超过六十日且导致合同目的不能实现的,任一方可解除受影响的未履行部分,已实际履行的服务按履行情况结算。',
'12.3. 开元云可通过平台公告、站内信、账户通知、电子邮件、短信或订单约定的方式发送通知。涉及费用、主要功能、数据处理、服务暂停终止或争议解决的重大事项,应以能够合理到达用户的显著方式通知。',
'12.4. 您应及时维护有效联系方式。因您未及时更新导致通知无法送达的,由您承担相应后果;开元云明知联系方式失效仍向该地址发送的除外。',
'<strong>12.5. 开元云可因法律变化、服务调整或安全需要修改本协议。对用户权利义务有重大影响的修改,应在生效前显著通知。用户不同意的,可在生效前停止使用并按适用规则终止未履行服务。法律另有规定的,从其规定。</strong>',
'<strong>13. 法律适用与其他</strong>',
'13.1. 本协议的订立、效力、解释、履行及争议解决适用中华人民共和国大陆地区法律。',
'13.2. 双方应先协商解决争议。协商不成的,任一方可向开元云住所地有管辖权的人民法院提起诉讼;消费者依法有权选择其他有管辖权法院的,从其规定。',
'13.3. 双方是独立合同主体。本协议不成立合伙、合资、劳动或未经明确授权的代理关系。',
'13.4. 一方未行使或迟延行使权利,不构成放弃。部分条款无效或不可执行的,不影响其他条款的效力。',
'13.5. 本协议以电子形式订立,与纸质协议具有同等法律效力。用户可通过平台或客服获取、保存和下载协议文本及交易记录。',
'13.6. 客服联系方式【400-6150805 010-65917875】电子邮箱【Open-computing@kaiyuancloud.cn】。联系方式变更的以开元云平台依法公示的信息为准。'
]
},
'privacy': {
'title': '隐私政策',
'paragraphs': [
'<strong>开元云隐私政策</strong>',
'版本更新日期【2026年7月30日】',
'版本生效日期【2026年7月30日】',
'开元云(北京)科技有限公司(以下简称“开元云”或“我们”)重视您的个人信息和隐私保护。本政策适用于我们通过开元云官方网站、开放算力应用服务平台及其他由我们运营并明确适用本政策的产品和服务(统称“开元云服务”)处理个人信息的活动。某项服务另有专门隐私规则的,专门规则优先适用;未约定的事项,适用本政策。',
'开元云服务涉及算力服务、算力网络、AI应用、云平台和相关技术服务。您代表单位使用服务的请确认已取得必要授权您向我们提供他人个人信息的应当确保来源合法并已依法履行告知、取得同意等义务。',
'请您在使用开元云服务前阅读本政策。涉及敏感个人信息、向其他个人信息处理者提供个人信息或向境外提供个人信息等依法需要单独同意的事项,我们将另行告知并依法取得您的单独同意。',
'<strong>一、定义</strong>',
'1. 个人信息:以电子或者其他方式记录的、与已识别或者可识别的自然人有关的各种信息,不包括匿名化处理后的信息。',
'2. 敏感个人信息:一旦泄露或者被非法使用,容易导致自然人的人格尊严受到侵害或者人身、财产安全受到危害的个人信息。开元云仅在特定目的、充分必要并采取严格保护措施的情况下处理敏感个人信息。',
'3. 匿名化:个人信息经过处理无法识别特定自然人且不能复原的过程。',
'4. 用户业务数据:用户在使用开元云服务过程中上传、生成、存储、传输或委托开元云处理的数据,不当然属于个人信息;其中含有个人信息的部分,依照适用法律和双方约定处理。',
'<strong>二、我们如何收集和使用个人信息</strong>',
'我们遵循合法、正当、必要和诚信原则,仅为明确、合理且与服务直接相关的目的处理个人信息。具体功能所需信息以实际页面、订单、合同或单独告知为准,主要包括:',
'1. 账号和联系信息。当您注册、登录或管理账号时,我们可能处理您的账号名称、手机号码、电子邮箱、密码密文及账号安全设置,用于创建账号、身份验证、发送必要通知和保障账号安全。拒绝提供必要信息可能导致无法使用账号功能,但通常不影响浏览公开内容。',
'2. 企业认证和交易信息。当您申请试用、购买算力或其他服务、签订或履行合同、结算或开具发票时,我们可能处理单位名称、统一社会信用代码、联系人及联系方式、服务配置、订单、合同、支付状态和开票信息,用于确认交易主体、交付服务、结算、售后和财务管理。支付机构直接处理的银行卡等信息由其依照自身规则处理,我们原则上仅接收完成交易所需的支付结果。',
'3. 咨询和服务记录。当您提交咨询、工单、投诉或参加业务活动时,我们可能处理您提交的姓名、联系方式、单位、需求描述、沟通记录和附件,用于回复请求、排查问题和改进服务。非提供服务所必需的调研或推广信息,我们将在必要时另行取得同意,并提供便捷的退订方式。',
'4. 设备、日志和安全信息。您访问或使用开元云服务时我们可能自动记录IP地址、浏览器和设备类型、访问时间、操作记录、故障日志及安全日志用于运行服务、定位故障、统计基本使用情况和防范网络攻击、欺诈或其他安全风险。我们不会仅因设备或日志信息而不合理限制您的服务。',
'5. 依法需要核验的信息。如特定产品、交易或监管要求确需进行个人或企业身份核验,我们可能处理姓名、身份证明或主体资质等必要信息,并在收集前另行说明具体目的、方式、范围和保存期限。涉及敏感个人信息的,我们将采取更严格的保护措施并依法取得单独同意;如有非敏感的替代核验方式,我们将按实际情况提供。',
'我们依据您的同意、订立或履行合同所必需、履行法定义务,或者法律规定的其他基础处理个人信息。处理目的、方式或个人信息种类发生变化的,我们将依法重新告知,并在需要时重新取得同意。除法律另有规定外,您可以撤回基于同意作出的授权;撤回不影响撤回前处理活动的效力。',
'<strong>三、Cookie和同类技术</strong>',
'1. 为保障网站正常运行、保持登录状态、保存必要设置、分析故障和防范安全风险我们可能使用Cookie和同类技术。必要Cookie被禁用后部分功能可能无法正常使用对于非必要Cookie我们将依法提供选择或关闭方式。',
'2. 您可以通过浏览器设置管理或删除Cookie。清除或拒绝Cookie可能使您需要重新登录或设置偏好但不影响与相关Cookie无关的服务。我们不会将Cookie用于本政策未说明的目的。',
'<strong>四、用户业务数据</strong>',
'1. 您或您的单位在使用算力、存储、网络、模型、智能文档处理或其他开元云服务时上传、生成、存储、传输或委托我们处理的数据,属于用户业务数据。其中含有个人信息的,您或您的单位通常决定处理目的和方式,我们按照双方协议和您的合法指示提供受托处理服务。',
'2. 您应当确保业务数据来源、内容及处理活动合法,并根据适用法律向相关个人履行告知、取得同意等义务。除非产品说明、订单或合同另有明确约定并具备合法处理基础,或者法律另有规定,我们不会将用户业务数据用于自身营销、训练通用模型或其他与提供约定服务无关的目的。',
'用户业务数据与我们为账号管理、交易结算、客户支持和安全保障而独立处理的信息,适用不同的责任分工。具体数据位置、备份、迁移、删除和安全要求,以对应产品说明、订单或合同为准。',
'<strong>五、委托处理、对外提供、转让和公开披露</strong>',
'1. 为提供和保障开元云服务,我们可能委托基础设施、算力、网络、模型接口、身份核验、支付结算、电子签约、发票、客服或安全服务提供方处理必要的个人信息。我们将根据服务性质选择合作方,通过合同约定处理目的、期限、方式、信息种类、安全措施和双方责任,并进行必要监督。合作方不得将受托信息用于自身目的。',
'2. 如需向其他个人信息处理者提供您的个人信息,我们将依法告知接收方信息、处理目的、方式和个人信息种类,并在法律要求时取得您的单独同意。涉及敏感个人信息的,我们还会说明必要性及对个人权益的影响。我们不会出售个人信息。',
'3. 发生合并、分立、重组、资产转让或类似交易而需要转移个人信息的,我们将向您告知接收方信息,并要求接收方继续履行本政策和法律规定的义务;接收方变更原处理目的或方式的,应当依法重新取得同意。',
'4. 我们原则上不公开披露个人信息。确需公开披露的,将告知披露目的、方式和信息种类,依法取得单独同意并采取相应保护措施,法律另有规定的除外。',
'<strong>六、个人信息的保存和安全保护</strong>',
'1. 我们按照实现处理目的所必要的最短时间保存个人信息;法律法规、监管规定或双方合同另有要求的,从其规定。保存期限届满后,我们将删除个人信息或进行匿名化处理;因技术原因暂时无法删除的,将停止除存储和采取必要安全保护措施之外的处理。',
'2. 我们在中华人民共和国境内收集和产生的个人信息原则上存储在境内。具体产品的数据中心和用户业务数据存储位置以产品说明、订单或合同为准。',
'3. 我们根据个人信息的种类、处理目的和风险采取与之相适应的安全措施,包括权限控制、身份认证、传输和存储保护、日志审计、备份恢复、人员管理及安全事件处置。互联网环境并非绝对安全,请您妥善保管账号和认证凭证,不要通过不安全渠道发送敏感信息。',
'4. 发生或者可能发生个人信息泄露、篡改、丢失时,我们将立即采取补救措施,并依照法律规定向主管部门报告;可能对您的权益造成危害的,我们将依法告知事件情况、可能影响、已采取或拟采取的措施及降低风险的建议。',
'<strong>七、您的权利</strong>',
'1. 在法律规定范围内,您有权知情、决定、限制或拒绝我们处理您的个人信息,并可请求查阅、复制、更正、补充或删除个人信息,撤回同意、注销账号,以及要求我们解释个人信息处理规则。我们利用个人信息进行自动化决策并对您的权益产生重大影响的,您有权要求说明,并有权拒绝仅通过自动化决策作出的决定。',
'2. 您可以通过产品提供的账号设置、工单或本政策所列联系方式提出请求。为保护账号和信息安全,我们可能验证您的身份,并在法律规定的期限内处理。请求明显不合理、超出必要限度,或法律规定可以不予响应的,我们可能拒绝或限制响应,并向您说明理由。',
'3. 账号注销后,我们将停止提供与账号相关的服务,并依法删除或匿名化处理相关个人信息;依法需要保留的信息,在保存期间仅用于履行法定义务或争议处理。注销前,请您按照产品说明妥善迁移或备份用户业务数据。',
'<strong>八、未成年人个人信息</strong>',
'不以不满十四周岁的未成年人应当在父母或其他监护人指导下使用开元云相关服务。我们发现未经监护人同意处理了不满十四周岁未成年人的个人信息时,将依法删除或采取其他必要措施。',
'<strong>九、个人信息跨境提供</strong>',
'1. 如特定服务需要向中华人民共和国境外提供个人信息,我们将仅在业务确有必要且符合法律规定的情况下进行,并在提供前告知境外接收方信息、处理目的和方式、个人信息种类以及您向境外接收方行使权利的方式和程序。我们将依法履行相应程序,取得单独同意,并要求境外接收方达到法律规定的个人信息保护标准。',
'2. 用户自行选择境外资源、境外模型或其他境外服务的,相关数据位置和跨境安排以对应产品说明、订单、合同及单独告知为准。',
'<strong>十、本政策的更新</strong>',
'1. 我们可能根据法律变化、业务调整或个人信息处理活动变化更新本政策。更新后的政策将通过网站、产品页面或其他适当方式发布。处理目的、方式、个人信息种类、保存期限或个人权利等发生重大变化的,我们将以显著方式通知;依法需要重新取得同意的,将在相关处理前完成。',
'2. 未经您的同意,我们不会通过更新本政策减损您依法享有的权利。',
'<strong>十一、如何联系我们</strong>',
'1. 如您对本政策或个人信息处理活动有疑问、意见、投诉,或需要行使个人信息权利,可通过以下方式联系开元云:',
'公司名称:【开元云(北京)科技有限公司】',
'联系地址【北京市朝阳区东三环中路65号富力中心】',
'联系电话【400-6150805 010-65917875】',
'联系邮箱【Open-computing@kaiyuancloud.cn】',
'2. 我们将在核验您的身份后依法处理。对处理结果有异议的,您可以再次向我们反馈,也可以依法向履行个人信息保护职责的部门投诉、举报或寻求其他救济。'
]
}
}

View File

@ -645,7 +645,19 @@ export default Vue.extend({
getLogoAPI(params).then((res) => {
if (res.status === true && res.data && res.data.length) {
const info = res.data[0]
this.$store.commit('setLogoInfoNew', info.additional_msg)
const additionalMsg = info.additional_msg || {}
const home = { ...(additionalMsg.home || {}) }
home.mobile = home.mobile || info.mobile || ''
home.email = home.email || info.email || ''
home.address_zh = home.address_zh || home.address || info.address || home.adress || ''
home.address_en = home.address_en || home.address_zh || home.address || info.address || home.adress || ''
home.adress = home.address_zh
this.$store.commit('setLogoInfoNew', {
...additionalMsg,
home
})
if (info.orgname !== '业主机构') {
this.$store.commit('setLogo', info.logo)
} else {

View File

@ -1,37 +1,37 @@
<template>
<div>
<el-dialog
title="联系销售"
:title="$t('contactSales.title')"
:visible="dialogVisible"
width="400px"
center
append-to-body
:close-on-click-modal="false"
@close="cancelBtn"
@update:visible="handleDialogVisibleUpdate"
top="8vh"
custom-class="talk-dialog"
@close="cancelBtn"
@update:visible="handleDialogVisibleUpdate"
>
<div class="talk-body">
<div class="talk-form">
<el-form ref="ruleForm" :rules="rules" label-position="top" label-width="80px" :model="addData">
<div class="form-grid">
<el-form-item label="1. 请填写您的姓名" prop="name">
<el-input v-model.trim="addData.name" maxlength="20" placeholder="请输入您的姓名"></el-input>
<el-form-item :label="$t('contactSales.nameLabel')" prop="name">
<el-input v-model.trim="addData.name" maxlength="20" :placeholder="$t('contactSales.namePlaceholder')" />
</el-form-item>
<el-form-item prop="phone" label="2. 请填写您的联系方式">
<el-input v-model.trim="addData.phone" maxlength="11" placeholder="请输入您的联系电话"></el-input>
<el-form-item prop="phone" :label="$t('contactSales.phoneLabel')">
<el-input v-model.trim="addData.phone" maxlength="11" :placeholder="$t('contactSales.phonePlaceholder')" />
</el-form-item>
<el-form-item label="3. 请填写您的邮箱" prop="email" class="form-item--compact">
<el-input v-model.trim="addData.email" maxlength="60" placeholder="请输入您的邮箱"></el-input>
<el-form-item :label="$t('contactSales.emailLabel')" prop="email" class="form-item--compact">
<el-input v-model.trim="addData.email" maxlength="60" :placeholder="$t('contactSales.emailPlaceholder')" />
</el-form-item>
<el-form-item label="4. 请填写您的公司名称" prop="company" class="form-item--compact">
<el-input v-model.trim="addData.company" maxlength="80" placeholder="请输入您的公司名称"></el-input>
<el-form-item :label="$t('contactSales.companyLabel')" prop="company" class="form-item--compact">
<el-input v-model.trim="addData.company" maxlength="80" :placeholder="$t('contactSales.companyPlaceholder')" />
</el-form-item>
<el-form-item label="5. 请选择您的企业类型(单选)" prop="enterprise_type" class="form-item--full">
<el-form-item :label="$t('contactSales.enterpriseLabel')" prop="enterprise_type" class="form-item--full">
<el-radio-group v-model="addData.enterprise_type" class="option-grid">
<el-radio
v-for="item in enterpriseOptions"
v-for="item in localizedEnterpriseOptions"
:key="item.id"
:label="item.id"
class="option-item"
@ -40,63 +40,71 @@
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="6. 请选择您所在的省份(单选)" prop="region" class="form-item--full">
<el-form-item :label="$t('contactSales.provinceLabel')" prop="region" class="form-item--full">
<el-select
:key="provinceSelectKey"
v-model="addData.region"
filterable
placeholder="输入省份名称或拼音首字母搜索..."
:placeholder="$t('contactSales.provincePlaceholder')"
class="full-select"
>
<el-option
v-for="item in provinceOptions"
v-for="item in localizedProvinceOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="7. 如果您有其他问题需要咨询,请留言" class="form-item--message">
<el-form-item :label="$t('contactSales.messageLabel')" class="form-item--message">
<el-input
v-model.trim="addData.content"
type="textarea"
:autosize="{ minRows: 3, maxRows: 5 }"
maxlength="500"
show-word-limit
placeholder="请输入您想咨询的内容..."
></el-input>
:placeholder="$t('contactSales.messagePlaceholder')"
/>
</el-form-item>
</div>
</el-form>
<el-checkbox class="agreement-checkbox" v-model="checked">
您填写的信息仅用于本次业务对接沟通公司将严格落实信息安全保护机制不泄露不滥用您的任何个人资料
<el-checkbox v-model="checked" class="agreement-checkbox">
{{ $t('contactSales.privacy') }}
</el-checkbox>
</div>
<div v-if="qrCodeUrl" class="qcode">
<img :src="qrCodeUrl" alt="官方客服二维码">
<span>扫码添加官方客服</span>
<span>{{ $t('contactSales.qrcode') }}</span>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="cancel-btn" @click="cancelBtn">取消</el-button>
<el-button class="submit-btn" type="primary" :loading="addBtnLoading" @click="confirmBtn">提交咨询</el-button>
<el-button class="cancel-btn" @click="cancelBtn">{{ $t('contactSales.cancel') }}</el-button>
<el-button class="submit-btn" type="primary" :loading="addBtnLoading" @click="confirmBtn">{{ $t('contactSales.submit') }}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Vue from 'vue'
import {mapState} from "vuex";
import {reqNewHomeConsult} from "@/api/newHome";
import {reqConsultForm} from "@/api/H5";
import { mapState } from 'vuex'
import { reqNewHomeConsult } from '@/api/newHome'
import { reqConsultForm } from '@/api/H5'
import {
extractConsultOptionList,
isEnglishLocale,
localizeDictOptions,
localizeDirectionOptions,
normalizeDictOptions as buildDictOptions
} from '@/utils/consultDict'
export default Vue.extend({
name: "talk",
name: 'Talk',
data() {
const validatePhone = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入联系电话'))
callback(new Error(this.$t('contactSales.phonePlaceholder')))
} else if (!/^1[3-9]\d{9}$/.test(value)) {
callback(new Error('请输入正确的手机号'))
callback(new Error(this.$t('contactSales.phoneInvalid') || '请输入正确的手机号'))
} else {
callback()
}
@ -105,23 +113,23 @@ export default Vue.extend({
return {
rules: {
name: [
{required: true, message: '请输入姓名', trigger: 'blur'},
{ required: true, message: this.$t('contactSales.namePlaceholder'), trigger: 'blur' }
],
phone: [
{required: true, validator: validatePhone, trigger: 'blur'}
{ required: true, validator: validatePhone, trigger: 'blur' }
],
email: [
{required: true, message: '请输入邮箱', trigger: 'blur'},
{type: 'email', message: '请输入正确的邮箱地址', trigger: 'blur'}
{ required: true, message: this.$t('contactSales.emailPlaceholder'), trigger: 'blur' },
{ type: 'email', message: this.$t('contactSales.emailInvalid') || '请输入正确的邮箱地址', trigger: 'blur' }
],
company: [
{required: true, message: '请输入公司名称', trigger: 'blur'}
{ required: true, message: this.$t('contactSales.companyPlaceholder'), trigger: 'blur' }
],
enterprise_type: [
{required: true, message: '请选择企业类型', trigger: 'change'}
{ required: true, message: this.$t('contactSales.enterpriseRequired') || '请选择企业类型', trigger: 'change' }
],
region: [
{required: true, message: '请选择所在省份', trigger: 'change'}
{ required: true, message: this.$t('contactSales.provinceRequired') || '请选择所在省份', trigger: 'change' }
]
},
addBtnLoading: false,
@ -129,15 +137,16 @@ export default Vue.extend({
dialogVisible: false,
enterpriseOptions: [],
provinceOptions: [],
provinceSelectKey: 0,
addData: {
content: '',//
custom_type: "1",// 0- 1-
name: "",//
phone: "",//
company: "",//
email: "",//
content: '', //
custom_type: '1', // 0- 1-
name: '', //
phone: '', //
company: '', //
email: '', //
enterprise_type: '',
region: '',
region: ''
},
labelPosition: 'right',
formLabelAlign: {
@ -147,7 +156,27 @@ export default Vue.extend({
}
}
},
computed: {
...mapState({
showTalk: (state) => state.product.showTalk,
logoInfoNew: state => state.product.logoInfoNew
}),
qrCodeUrl() {
return this.logoInfoNew && this.logoInfoNew.home && this.logoInfoNew.home.qrCode
? this.logoInfoNew.home.qrCode
: ''
},
localizedEnterpriseOptions() {
return localizeDictOptions(this.enterpriseOptions, isEnglishLocale(this.$i18n))
},
localizedProvinceOptions() {
return localizeDictOptions(this.provinceOptions, isEnglishLocale(this.$i18n))
}
},
watch: {
'$i18n.locale'() {
this.provinceSelectKey += 1
},
showTalk: {
immediate: true,
handler(value) {
@ -168,52 +197,41 @@ export default Vue.extend({
company: '',
email: '',
enterprise_type: '',
region: '',
region: ''
}
},
normalizeDictOptions(list, type) {
return list
.filter(item => item && item.dict_type === type)
.sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0))
.map(item => ({
id: item.dict_key,
name: item.dict_value
}))
},
extractConsultOptionList(res) {
if (res && Array.isArray(res.data)) return res.data
if (res && res.data && Array.isArray(res.data.data)) return res.data.data
return []
},
async fetchConsultOptions() {
try {
const res = await reqConsultForm()
const list = this.extractConsultOptionList(res)
const list = extractConsultOptionList(res)
if (!list.length) return
const enterpriseOptions = this.normalizeDictOptions(list, 'enterprise_type')
const provinceOptions = this.normalizeDictOptions(list, 'region')
const enterpriseOptions = buildDictOptions(list, 'enterprise_type')
const provinceOptions = buildDictOptions(list, 'region')
if (enterpriseOptions.length) this.enterpriseOptions = enterpriseOptions
if (provinceOptions.length) this.provinceOptions = provinceOptions
if (provinceOptions.length) {
this.provinceOptions = provinceOptions
this.provinceSelectKey += 1
}
} catch (error) {
//
}
},
handleDialogVisibleUpdate(value) {
this.dialogVisible = value;
this.dialogVisible = value
if (!value) {
this.$store.commit('setShowTalk', false);
this.$store.commit('setShowTalk', false)
}
},
cancelBtn() {
this.dialogVisible = false;
this.$store.commit('setShowTalk', false);
this.dialogVisible = false
this.$store.commit('setShowTalk', false)
},
confirmBtn() {
if (!this.checked) {
this.$message.warning('请勾选同意协议后再提交!');
return;
this.$message.warning(this.$t('contactSales.privacyRequired') || '请勾选同意协议后再提交!')
return
}
this.$refs['ruleForm'].validate((valid) => {
if (valid) {
@ -229,41 +247,28 @@ export default Vue.extend({
this.$message({
type: 'success',
message: '感谢您关注人工智能服务平台,我们将尽快联系您!~'
});
this.$store.commit('setShowTalk', false);
})
this.$store.commit('setShowTalk', false)
this.addData = this.getDefaultFormData()
this.checked = false
} else {
this.$message.error(response.msg || '提交失败,请稍后再试!');
this.$message.error(response.msg || '提交失败,请稍后再试!')
}
}).catch(error => {
console.error("提交咨询失败:", error);
this.$message.error('提交失败,请稍后再试!');
console.error('提交咨询失败:', error)
this.$message.error('提交失败,请稍后再试!')
})
} else {
this.$message.error('请完善表单信息~')
return false;
this.$message.error(this.$t('contactSales.formInvalid') || '请完善表单信息~')
return false
}
});
})
}
},
computed: {
...mapState({
showTalk: (state) => state.product.showTalk,
logoInfoNew: state => state.product.logoInfoNew,
}),
qrCodeUrl() {
return this.logoInfoNew && this.logoInfoNew.home && this.logoInfoNew.home.qrCode
? this.logoInfoNew.home.qrCode
: ''
},
},
}
})
</script>
<style scoped lang="scss">
::v-deep .talk-dialog {
border-radius: 22px;
@ -376,7 +381,21 @@ export default Vue.extend({
}
.form-item--message {
width: 100%;
}
::v-deep .form-item--message .el-form-item__label {
width: 100% !important;
float: none;
line-height: 1.5;
white-space: normal;
word-break: normal;
overflow-wrap: break-word;
}
::v-deep .form-item--message .el-form-item__content {
width: calc(100% - 184px);
max-width: calc(100% - 184px);
}
.full-select {
@ -520,6 +539,11 @@ export default Vue.extend({
width: 100%;
}
::v-deep .form-item--message .el-form-item__content {
width: 100%;
max-width: 100%;
}
.agreement-checkbox {
max-width: 100%;
}

View File

@ -24,7 +24,7 @@
<h4 class="footer-col-title">{{ $t('home.footerProducts') }}</h4>
<ul class="footer-link-list">
<li
v-for="item in footerProductServices"
v-for="item in localizedFooterProductServices"
:key="item.label"
class="footer-link-item"
:class="{ clickable: !!item.path }"
@ -38,9 +38,18 @@
<div class="footer-contact-col">
<h4 class="footer-col-title">{{ $t('home.footerContact') }}</h4>
<ul class="footer-contact-list">
<li>地址<span>{{ footerHomeInfo.adress }}</span></li>
<li>邮箱<span>{{ footerHomeInfo.email }}</span></li>
<li>电话<span>{{ footerHomeInfo.mobile }}</span></li>
<li>
<span class="footer-contact-label">{{ $t('home.footerAddress') }}:</span>
<span class="footer-contact-value">{{ localizedFooterAddress }}</span>
</li>
<li>
<span class="footer-contact-label">{{ $t('home.footerEmail') }}:</span>
<span class="footer-contact-value">{{ footerHomeInfo.email }}</span>
</li>
<li>
<span class="footer-contact-label">{{ $t('home.footerTel') }}:</span>
<span class="footer-contact-value">{{ localizedFooterMobile }}</span>
</li>
</ul>
<div v-if="showFooterQrcode" class="footer-qrcode-row">
<div class="qr-box">
@ -53,7 +62,7 @@
<div class="qr-code">
<img src="./img/kefu.jpg" alt="">
</div>
<span class="qr-content">关注公众号</span>
<span class="qr-content">{{ $t('home.followOfficialAccount') }}</span>
</div>
</div>
@ -71,7 +80,7 @@
}}&nbsp;
<span style="padding: 4px;"></span>
</span> &nbsp;&nbsp;{{
footerHomeInfo.footerTitle
localizedFooterTitle
}}&nbsp;{{
footerHomeInfo.copyright
}}&nbsp; </span>
@ -133,12 +142,13 @@ export default Vue.extend({
}
],
footerProductServices: [
{ label: 'Token市集', path: '/homePage/tokenMarket' },
{ label: '算力市场', path: '/homePage/computeMarket' },
{ label: 'OPC公共服务平台', path: '/homePage/opc' },
{ label: '训推平台', path: '/homePage/trainPlatform' },
{ label: '智能体商店', path: '/homePage/agentStore' },
{ label: '供需广场', path: '/ncmatchHome/supplyAndDemandSquare' },
{ action: 'tokenMarket', label: 'Token市集', path: '/homePage/tokenMarket' },
{ action: 'computeMarket', label: '算力市场', path: '/homePage/computeMarket' },
{ action: 'opc', label: 'OPC公共服务平台', path: '/homePage/opc' },
{ action: 'yuanjing', label: '元境', path: '/homePage/yuanJing' },
{ action: 'trainPlatform', label: '训推平台', path: '/homePage/trainPlatform' },
{ action: 'agentStore', label: '智能体商店', path: '/homePage/agentStore' },
{ action: 'supplySquare', label: '供需广场', path: '/ncmatchHome/supplyAndDemandSquare' },
],
footerAboutUs: [
{ label: '关于我们', path: '/homePage/about' },
@ -189,9 +199,49 @@ export default Vue.extend({
footerHomeInfo() {
return this.hasLogoInfo ? this.logoInfoNew.home : {}
},
isEnglishLocale() {
return !!(this.$i18n && this.$i18n.locale === 'en-US')
},
localizedFooterAddress() {
const info = this.footerHomeInfo
if (!info || !Object.keys(info).length) return ''
if (this.isEnglishLocale) {
return info.address_en || info.address || info.adress || info.address_zh || ''
}
return info.address_zh || info.address || info.adress || info.address_en || ''
},
localizedFooterMobile() {
const info = this.footerHomeInfo
return (info && (info.mobile || info.tel || info.phone)) || ''
},
localizedFooterTitle() {
const info = this.footerHomeInfo
if (!info || !Object.keys(info).length) return ''
if (this.isEnglishLocale) {
return info.footerTitle_en || info.footerTitleEn || info.footerTitle || ''
}
return info.footerTitle || info.footerTitle_zh || ''
},
showFooterQrcode() {
return this.hasLogoInfo && this.footerHomeInfo.bannerTitle !== '开元数智'
},
localizedFooterProductServices() {
const labels = {
opc: 'OPC',
computeMarket: this.isEnglishLocale ? 'Compute Market' : '算力市场',
tokenMarket: this.isEnglishLocale ? 'Token Market' : 'Token市集',
yuanjing: this.isEnglishLocale ? 'Yuanjing' : '元境',
trainPlatform: this.isEnglishLocale ? 'Train & Infer' : '训推平台',
agentStore: this.isEnglishLocale ? 'Agent Store' : '智能体商店',
supplySquare: this.isEnglishLocale ? 'Supply Square' : '供需广场'
}
return this.footerProductServices.map(item => ({
...item,
label: labels[item.action] || item.label
}))
},
username() {
return sessionStorage.getItem('username') || '';
},
@ -390,10 +440,28 @@ export default Vue.extend({
list-style: none;
color: #5d6477;
font-size: 14px;
line-height: 1.6;
line-height: 1.75;
li {
margin-bottom: 5px;
display: flex;
align-items: flex-start;
gap: 10px;
margin-bottom: 10px;
}
li:last-child {
margin-bottom: 0;
}
.footer-contact-label {
flex: 0 0 auto;
white-space: nowrap;
}
.footer-contact-value {
flex: 1;
min-width: 0;
word-break: break-word;
}
}

View File

@ -825,11 +825,13 @@ body.dark-theme .bg-orb {
h3 {
position: relative;
z-index: 1;
width: 100%;
margin: 24px 0 8px;
font-size: 24px;
line-height: 1.3;
font-weight: 800;
letter-spacing: 2px;
text-align: center;
}
span {
@ -872,10 +874,12 @@ body.dark-theme .bg-orb {
.solution-card__front {
position: relative;
z-index: 1;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
transition: all 0.28s ease;
}
@ -1321,6 +1325,7 @@ body.dark-theme .bg-orb {
font-size: 34px;
line-height: 1.25;
font-weight: 800;
text-align: center ;
}
p {

View File

@ -9,11 +9,11 @@
<div class="news-hero-glow news-hero-glow-2"></div>
<div class="news-shell">
<div class="hero-content">
<span class="hero-badge">COMPANY NEWS</span>
<span class="hero-badge">{{ $t('newsView.badge') }}</span>
<div class="hero-title-row">
<h1>{{ isEnglish ? 'Company News' : '企业动态' }}</h1>
<h1>{{ $t('newsView.title') }}</h1>
</div>
<p>{{ isEnglish ? 'Stay up to date with Open Computing AI, explore the latest AI industry insights, and witness the intelligent leap with us.' : '了解开元云最新动态把握AI行业前沿资讯与我们一起见证智能跃迁' }}</p>
<p>{{ $t('newsView.intro') }}</p>
</div>
</div>
</section>
@ -22,7 +22,7 @@
<div class="news-shell">
<div class="filter-tabs">
<button
v-for="item in filterTabs"
v-for="item in localizedFilterTabs"
:key="item.value"
type="button"
class="filter-tab"
@ -39,7 +39,7 @@
<div class="news-shell">
<article v-if="featuredNews" class="news-featured" @click="goNewsDetail(featuredNews)">
<div class="news-item-glow"></div>
<span class="hover-detail">详情 <i class="el-icon-arrow-right"></i></span>
<span class="hover-detail">{{ $t('newsView.detail') }} <i class="el-icon-arrow-right"></i></span>
<div class="news-featured-inner">
<div class="news-featured-img">
<img :src="featuredNews.img || fallbackNewsImage" :alt="featuredNews.title" @error="handleImageError">
@ -68,7 +68,7 @@
@click="goNewsDetail(item)"
>
<div class="news-item-glow"></div>
<span class="hover-detail">详情 <i class="el-icon-arrow-right"></i></span>
<span class="hover-detail">{{ $t('newsView.detail') }} <i class="el-icon-arrow-right"></i></span>
<div class="news-item-img">
<img :src="item.img || fallbackNewsImage" :alt="item.title" @error="handleImageError">
<div class="news-item-img-overlay"></div>
@ -108,7 +108,7 @@
<script>
import { reqNewsList } from '@/api/newsapi/newsapi'
export default {
name: 'NewsView',
name: 'NewsView',
data() {
return {
fallbackNewsImage: require('@/assets/image/news.jpg'),
@ -116,12 +116,12 @@ export default {
page: 1,
pageSize: 10,
total: 0,
filterTabs: [
{ label: '全部', value: 'all' },
{ label: '企业动态', value: '企业动态' },
{ label: '产品动态', value: '产品动态' },
{ label: '行业洞察', value: '行业洞察' },
{ label: '活动资讯', value: '活动资讯' }
filterTabValues: [
{ key: 'all', value: 'all', zh: '', en: '' },
{ key: 'corporate', value: 'corporate', zh: '企业动态', en: 'Corporate News' },
{ key: 'product', value: 'product', zh: '产品动态', en: 'Product News' },
{ key: 'industry', value: 'industry', zh: '行业洞察', en: 'Industry Insights' },
{ key: 'event', value: 'event', zh: '活动资讯', en: 'Event News' }
],
newsList: []
}
@ -136,6 +136,12 @@ export default {
filteredNewsList() {
return this.newsList.slice(1)
},
localizedFilterTabs() {
return this.filterTabValues.map(item => ({
...item,
label: item.key === 'all' ? this.$t('newsView.all') : this.$t(`newsView.categories.${item.key}`)
}))
},
totalPages() {
return Math.max(Math.ceil(this.total / this.pageSize), 1)
},
@ -179,27 +185,53 @@ export default {
this.page = page
this.getNewsList()
},
getActiveCategoryConfig() {
return this.filterTabValues.find(item => item.value === this.activeCategory) || this.filterTabValues[0]
},
buildNewsParams() {
const category = this.getActiveCategoryConfig()
return {
url_link: window.location.href.split('#')[0] || window.location.href,
title_zh: '',
title_en: '',
article_type_zh: category.zh || '',
article_type_en: category.en || '',
current_page: String(this.page),
page_size: String(this.pageSize),
article_type: this.activeCategory === 'all' ? '' : this.activeCategory,
title: ''
page_size: String(this.pageSize)
}
},
getTagColor(type) {
const map = {
企业动态: 'rgba(16,185,129,0.85)',
产品动态: 'rgba(99,102,241,0.85)',
行业洞察: 'rgba(13,148,136,0.85)',
活动资讯: 'rgba(245,158,11,0.85)',
'Corporate News': 'rgba(16,185,129,0.85)',
'Product News': 'rgba(99,102,241,0.85)',
'Industry Insights': 'rgba(13,148,136,0.85)',
'Event News': 'rgba(245,158,11,0.85)'
corporate: 'rgba(16,185,129,0.85)',
product: 'rgba(99,102,241,0.85)',
industry: 'rgba(13,148,136,0.85)',
event: 'rgba(245,158,11,0.85)'
}
return map[type] || 'rgba(99,102,241,0.85)'
return map[this.getCategoryKey(type)] || 'rgba(99,102,241,0.85)'
},
getCategoryKey(type) {
const map = {
企业动态: 'corporate',
'Corporate News': 'corporate',
产品动态: 'product',
'Product News': 'product',
行业洞察: 'industry',
'Industry Insights': 'industry',
活动资讯: 'event',
'Event News': 'event'
}
if (map[type]) return map[type]
const matchedLabel = Object.keys(map).find(label => String(type || '').startsWith(label))
return matchedLabel ? map[matchedLabel] : ''
},
getCategorySuffix(type) {
const labels = ['企业动态', 'Corporate News', '产品动态', 'Product News', '行业洞察', 'Industry Insights', '活动资讯', 'Event News']
const matchedLabel = labels.find(label => String(type || '').startsWith(label))
return matchedLabel ? String(type).slice(matchedLabel.length) : ''
},
getLocalizedCategory(type) {
const key = this.getCategoryKey(type)
return key ? `${this.$t(`newsView.categories.${key}`)}${this.getCategorySuffix(type)}` : type
},
getLocalizedField(row, zhField, enField, legacyField) {
if (this.isEnglish && row[enField]) return row[enField]
@ -212,10 +244,11 @@ export default {
},
normalizeNewsItem(row) {
const type = this.getLocalizedField(row, 'article_type_zh', 'article_type_en', 'article_type') || '企业动态'
const localizedType = this.getLocalizedCategory(type)
return {
id: row.id,
category: type,
tag: type,
category: localizedType,
tag: localizedType,
tagColor: this.getTagColor(type),
date: this.getLocalizedField(row, 'publish_time_zh', 'publish_time_en', 'publish_time'),
title: this.getLocalizedField(row, 'title_zh', 'title_en', 'title') || '未命名文章',
@ -240,7 +273,7 @@ export default {
} catch (error) {
this.newsList = []
this.total = 0
this.$message.error('新闻列表加载失败')
this.$message.error(this.$t('newsView.loadFail'))
}
}
}