offline-evaluate.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
  2. import { evaluateOrderGoodsMethod } from "../../request";
  3. import { upload } from "../../../../lib/request/upload";
  4. import { OfflineEvaluateModel } from "../../model/evaluate.model";
  5. function withMediaType(url: string, type: "image" | "video") {
  6. if (!url) return url;
  7. const hasQuery = url.includes("?");
  8. const hasHash = url.includes("#");
  9. if (hasHash) {
  10. const [base, hash] = url.split("#");
  11. return `${base}${hasQuery ? "&" : "?"}type=${type}#${hash ?? ""}`;
  12. }
  13. return `${url}${hasQuery ? "&" : "?"}type=${type}`;
  14. }
  15. Page({
  16. behaviors: [PageContainerBehavior],
  17. data: {
  18. orderId: "",
  19. service: {} as OfflineEvaluateModel,
  20. scoreServiceQuality: 0,
  21. scoreAttitude: 0,
  22. scoreEnvironment: 0,
  23. rateColor: "#F7BA2A",
  24. content: "",
  25. mediaList: [] as { path: string; type: "image" | "video" }[],
  26. canPublish: false,
  27. videoFullscreen: false,
  28. },
  29. onLoad(options: Record<string, string>) {
  30. let service = {} as OfflineEvaluateModel;
  31. if (options.goodsInfo) {
  32. const goods = JSON.parse(decodeURIComponent(options.goodsInfo));
  33. service = {
  34. lineId: goods.id || 0,
  35. patientConditioningRecordId: goods.patientConditioningRecordId || 0,
  36. patientConditioningProgramId: goods.patientConditioningProgramId || 0,
  37. operateTime: goods.operateTime || "",
  38. operateBy: goods.operateBy || "",
  39. conditioningProgramSupplierName: goods.conditioningProgramSupplierName || "",
  40. image: goods.conditioningProgramPhoto || "",
  41. name: goods.conditioningProgramName || "",
  42. };
  43. console.log(service, "service===");
  44. }
  45. this.setData({
  46. service,
  47. canPublish: this._checkCanPublish(0, 0, 0),
  48. });
  49. },
  50. _checkCanPublish(
  51. quality: number,
  52. attitude: number,
  53. environment: number
  54. ): boolean {
  55. return quality > 0 && attitude > 0 && environment > 0;
  56. },
  57. _updateCanPublish() {
  58. const { scoreServiceQuality, scoreAttitude, scoreEnvironment } = this.data;
  59. this.setData({
  60. canPublish: this._checkCanPublish(
  61. scoreServiceQuality,
  62. scoreAttitude,
  63. scoreEnvironment
  64. ),
  65. });
  66. },
  67. onScoreServiceQuality(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  68. const scoreServiceQuality = e.detail?.value ?? 0;
  69. this.setData({ scoreServiceQuality }, () => this._updateCanPublish());
  70. },
  71. onScoreAttitude(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  72. const scoreAttitude = e.detail?.value ?? 0;
  73. this.setData({ scoreAttitude }, () => this._updateCanPublish());
  74. },
  75. onScoreEnvironment(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  76. const scoreEnvironment = e.detail?.value ?? 0;
  77. this.setData({ scoreEnvironment }, () => this._updateCanPublish());
  78. },
  79. onContentInput(e: WechatMiniprogram.Input) {
  80. const content = e.detail?.value ?? "";
  81. this.setData({ content });
  82. },
  83. onChooseMedia() {
  84. const current = this.data.mediaList.length;
  85. if (current >= 9) {
  86. wx.showToast({ title: "图片和视频总数不能超过9个", icon: "none" });
  87. return;
  88. }
  89. const remain = 9 - current;
  90. wx.chooseMedia({
  91. count: remain,
  92. mediaType: ["image", "video"],
  93. sourceType: ["album", "camera"],
  94. maxDuration: 30,
  95. camera: "back",
  96. success: (res) => {
  97. const list = res.tempFiles.map((f) => ({
  98. path: f.tempFilePath,
  99. type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
  100. }));
  101. const oldLength = this.data.mediaList.length;
  102. const next = [...this.data.mediaList, ...list].slice(0, 9);
  103. this.setData({ mediaList: next });
  104. // 选取本地媒体后,调用上传接口上传到服务器
  105. list.forEach((item, idx) => {
  106. const index = oldLength + idx;
  107. upload<string, any>({
  108. params: { name: "file", file: item.path },
  109. transform({ data }: any): string {
  110. return (data as any)?.url || (data as any);
  111. },
  112. }).then(
  113. (url) => {
  114. const key = `mediaList[${index}].path`;
  115. this.setData({ [key]: url });
  116. },
  117. (error: any) => {
  118. wx.showToast({
  119. title: error?.errMsg || "上传失败",
  120. icon: "none",
  121. });
  122. const mediaList = this.data.mediaList.filter((_, i) => i !== index);
  123. this.setData({ mediaList });
  124. }
  125. );
  126. });
  127. },
  128. });
  129. },
  130. onRemoveMedia(e: WechatMiniprogram.TouchEvent) {
  131. const index = e.currentTarget.dataset.index as number;
  132. const mediaList = this.data.mediaList.filter((_, i) => i !== index);
  133. this.setData({ mediaList });
  134. },
  135. onPreviewImage(e: WechatMiniprogram.TouchEvent) {
  136. const url = e.currentTarget.dataset.url as string;
  137. const urls = this.data.mediaList.filter((m) => m.type === "image").map((m) => m.path);
  138. if (url && urls.length) {
  139. wx.previewImage({ current: url, urls });
  140. }
  141. },
  142. onPreviewVideo(e: WechatMiniprogram.TouchEvent) {
  143. const index = e.currentTarget.dataset.index as number;
  144. const videoContext = wx.createVideoContext("offline-video-" + index, this);
  145. videoContext.requestFullScreen({});
  146. },
  147. /** 点击图片/视频:原生全屏预览(类似 test 页) */
  148. onPreviewMedia(e: WechatMiniprogram.TouchEvent) {
  149. const index = e.currentTarget.dataset.index as number;
  150. const { mediaList } = this.data;
  151. if (index < 0 || index >= mediaList.length) return;
  152. const sources = mediaList.map((m) => ({
  153. url: m.path,
  154. type: m.type as "image" | "video",
  155. }));
  156. const previewMedia = (wx as any).previewMedia as
  157. | ((option: { sources: { url: string; type: "image" | "video" }[]; current: number }) => void)
  158. | undefined;
  159. if (typeof previewMedia === "function") {
  160. previewMedia({ sources, current: index });
  161. return;
  162. }
  163. // 低版本兜底:图片用 previewImage,视频用 requestFullScreen
  164. const current = mediaList[index];
  165. if (current.type === "image") {
  166. const urls = mediaList.filter((m) => m.type === "image").map((m) => m.path);
  167. wx.previewImage({ current: current.path, urls });
  168. return;
  169. }
  170. const ctx = wx.createVideoContext("offline-video-" + index, this);
  171. ctx.requestFullScreen({});
  172. },
  173. onVideoFullscreenChange(e: WechatMiniprogram.VideoFullScreenChange) {
  174. const fullScreen = !!(e.detail && e.detail.fullScreen);
  175. this.setData({ videoFullscreen: fullScreen });
  176. },
  177. onRemoveService() {
  178. this.setData({
  179. service: {} as OfflineEvaluateModel,
  180. });
  181. },
  182. async onPublish() {
  183. if (!this.data.canPublish) {
  184. wx.showToast({ title: "请完成三项评分", icon: "none" });
  185. return;
  186. }
  187. try {
  188. const data = {
  189. lineId: this.data.service?.lineId,
  190. patientConditioningRecordId: this.data.service?.patientConditioningRecordId,
  191. patientConditioningProgramId: this.data.service?.patientConditioningProgramId,
  192. complianceScore: this.data.scoreServiceQuality,
  193. qualityScore: this.data.scoreServiceQuality,
  194. attitudeScore: this.data.scoreAttitude,
  195. environmentScore: this.data.scoreEnvironment,
  196. depict: this.data.content,
  197. imageVideos: this.data.mediaList.map((m) => withMediaType(m.path, m.type)),
  198. };
  199. wx.showLoading({ title: "发布中..." });
  200. await evaluateOrderGoodsMethod(data);
  201. wx.hideLoading();
  202. wx.showToast({ title: "发布成功", icon: "success" });
  203. wx.redirectTo({
  204. url: `/module/care/pages/care/verifyRecord?id=${this.data.service?.patientConditioningProgramId}`,
  205. });
  206. } catch (error: any) {
  207. wx.hideLoading();
  208. wx.showToast({ title: error.errMsg || "发布失败", icon: "none" });
  209. }
  210. },
  211. });