index.tsx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import {
  2. Button,
  3. Form,
  4. Image,
  5. Input,
  6. Modal,
  7. Select,
  8. Skeleton,
  9. Breadcrumb,
  10. message,
  11. notification,
  12. Tooltip,
  13. } from "antd";
  14. import type { BreadcrumbProps } from "antd";
  15. import { useMemo, useState } from "react";
  16. import { useParams, useRequest, history } from "umi";
  17. import { GetAppDetail } from "@/api/appStore";
  18. import { GetTemplateDetail } from "@/api/templateStore";
  19. import styles from "./index.less";
  20. import { LeftOutlined } from "@ant-design/icons";
  21. import { SubmitApply } from "@/api/apply";
  22. export default function detail() {
  23. const [showAdvisory, setShowAdvisory] = useState(false);
  24. const [form] = Form.useForm();
  25. const { id, type } = useParams();
  26. const { data, loading } = useRequest<{ result: any }>(
  27. type === "application" ? GetAppDetail : GetTemplateDetail,
  28. {
  29. defaultParams: [
  30. {
  31. id: id,
  32. },
  33. ],
  34. }
  35. );
  36. const handleToApp = () => {
  37. if (data?.result?.trialUrl) {
  38. window.open(data?.result?.trialUrl, "_blank");
  39. }
  40. };
  41. const handleBack = () => {
  42. history.back();
  43. };
  44. // 提交申请
  45. const handleSubmit = () => {
  46. form.validateFields().then(async (values) => {
  47. await SubmitApply({
  48. ...values,
  49. type: type === "application" ? 0 : 1,
  50. templateId: id,
  51. });
  52. notification.success({
  53. message: "您的申请已提交,后续会有专员与您联系!~",
  54. });
  55. setShowAdvisory(false);
  56. });
  57. };
  58. const breadcrumbItems: BreadcrumbProps["items"] = useMemo(() => {
  59. return [
  60. {
  61. key: "all",
  62. // title: (
  63. // <a onClick={handleBack}>
  64. // <LeftOutlined />
  65. // <span className="m-l-4px">返回</span>
  66. // </a>
  67. // ),
  68. title: "全部",
  69. },
  70. { key: "current", title: data?.result.name },
  71. ];
  72. }, [data]);
  73. return (
  74. <div className="detail relative mx-auto pt-24px h-full overflow-y-auto">
  75. <div className="max-w-[1200px] mx-auto">
  76. <Breadcrumb className="mb-24px" items={breadcrumbItems} />
  77. <Skeleton avatar active loading={loading}>
  78. <div className="flex mb-32px">
  79. <div className="w-128px h-128px rounded-20px bg-gray-200 overflow-hidden flex justify-center items-center">
  80. <Image
  81. className="w-full h-full"
  82. preview={false}
  83. src={
  84. data?.result?.icon
  85. ? `/api/File/Download?fileId=${data?.result?.icon}`
  86. : ""
  87. }
  88. />
  89. </div>
  90. <div className="flex-1 mx-24px">
  91. <div className="text-32px font-[600]">{data?.result?.name}</div>
  92. <div className="text-secondary text-14px">
  93. {data?.result?.desc || "暂无描述"}
  94. </div>
  95. <div className="mt-12px flex items-center">
  96. {/* <div className="block bg-[#dcdde0] rounded-8px text-secondary px-8px py-4px text-12px">
  97. <i className="iconfont icon-qiyexinxi mr-8px" />
  98. <span>{data?.result?.createByName || "易码工坊"}</span>
  99. </div> */}
  100. <div className="flex items-center px-[14px] leading-24px text-12px">
  101. <div className="flex items-center space-x-1 text-text-tertiary">
  102. {/* <svg
  103. viewBox="0 0 24 24"
  104. xmlns="http://www.w3.org/2000/svg"
  105. width="24"
  106. height="24"
  107. fill="currentColor"
  108. className="remixicon shrink-0 w-3 h-3"
  109. >
  110. <path d="M9 2V4H5L4.999 14H18.999L19 4H15V2H20C20.5523 2 21 2.44772 21 3V21C21 21.5523 20.5523 22 20 22H4C3.44772 22 3 21.5523 3 21V3C3 2.44772 3.44772 2 4 2H9ZM18.999 16H4.999L5 20H19L18.999 16ZM17 17V19H15V17H17ZM13 2V7H16L12 11L8 7H11V2H13Z"></path>
  111. </svg> */}
  112. <i className="iconfont icon-liulanliang"/>
  113. <div className="system-xs-regular">浏览量 {data?.result?.viewCount || 0}</div>
  114. </div>
  115. <div className="mx-2 text-text-quaternary system-xs-regular">
  116. ·
  117. </div>
  118. <div className="flex flex-wrap space-x-2 h-4 overflow-hidden">
  119. {(data?.result.tags?.split(",") || []).map(
  120. (tag: string) => {
  121. return (
  122. <div
  123. className="flex space-x-1 system-xs-regular max-w-[120px] overflow-hidden"
  124. title={`# ${tag}`}
  125. >
  126. <span className="text-text-quaternary">#</span>
  127. <span className="truncate text-text-tertiary">
  128. {tag}
  129. </span>
  130. </div>
  131. );
  132. }
  133. )}
  134. </div>
  135. </div>
  136. </div>
  137. </div>
  138. <div className="head-right flex flex-col justify-center items-center">
  139. <Tooltip title={!data?.result?.isCanUseTrial ? "暂不支持体验~" : ""}>
  140. <Button
  141. type="primary"
  142. className="w-full mb-24px"
  143. onClick={handleToApp}
  144. disabled={!data?.result?.isCanUseTrial}
  145. >
  146. 在线体验
  147. </Button>
  148. </Tooltip>
  149. <Button className="w-full" onClick={() => setShowAdvisory(true)}>
  150. 购买咨询
  151. </Button>
  152. </div>
  153. </div>
  154. </Skeleton>
  155. <div className="inline-block">
  156. <div className="text-24px font-[600] mb-8px">方案详情</div>
  157. <div className="w-60px h-4px bg-primary rounded-4px mx-auto" />
  158. </div>
  159. <Skeleton active loading={loading}>
  160. <div
  161. className={
  162. "content m-y-32px overflow-hidden relative " + styles.rich
  163. }
  164. >
  165. <div
  166. dangerouslySetInnerHTML={{ __html: data?.result?.detail || "" }}
  167. />
  168. </div>
  169. </Skeleton>
  170. </div>
  171. <Modal
  172. title="购买咨询"
  173. width={500}
  174. open={showAdvisory}
  175. onCancel={() => setShowAdvisory(false)}
  176. onOk={handleSubmit}
  177. >
  178. <Form labelCol={{ span: 6 }} autoComplete="off" form={form}>
  179. <Form.Item
  180. label="如何称呼您?"
  181. name="name"
  182. rules={[{ required: true, message: "请输入您的称呼!" }]}
  183. >
  184. <Input placeholder="请输入" maxLength={20} />
  185. </Form.Item>
  186. <Form.Item
  187. label="联系方式"
  188. name="tel"
  189. rules={[
  190. { required: true, message: "请输入您的联系方式!", max: 20 },
  191. ]}
  192. >
  193. <Input placeholder="请输入" maxLength={20} />
  194. </Form.Item>
  195. <Form.Item label="公司名称" name="companyName">
  196. <Input placeholder="请输入" maxLength={100} />
  197. </Form.Item>
  198. <Form.Item label="企业规模" name="companySize">
  199. <Select
  200. placeholder="请选择"
  201. options={[
  202. { label: "1-10人", value: "1-10人" },
  203. { label: "11-50人", value: "11-50人" },
  204. { label: "51-200人", value: "51-200人" },
  205. { label: "200人以上", value: "200人以上" },
  206. ]}
  207. />
  208. </Form.Item>
  209. <Form.Item label="您的职务" name="jobTitle">
  210. <Input placeholder="请输入" maxLength={20} />
  211. </Form.Item>
  212. </Form>
  213. </Modal>
  214. </div>
  215. );
  216. }