offline-evaluate.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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.image || "",
  41. };
  42. console.log(service, "service===");
  43. }
  44. this.setData({
  45. service,
  46. canPublish: this._checkCanPublish(0, 0, 0),
  47. });
  48. },
  49. _checkCanPublish(
  50. quality: number,
  51. attitude: number,
  52. environment: number
  53. ): boolean {
  54. return quality > 0 && attitude > 0 && environment > 0;
  55. },
  56. _updateCanPublish() {
  57. const { scoreServiceQuality, scoreAttitude, scoreEnvironment } = this.data;
  58. this.setData({
  59. canPublish: this._checkCanPublish(
  60. scoreServiceQuality,
  61. scoreAttitude,
  62. scoreEnvironment
  63. ),
  64. });
  65. },
  66. onScoreServiceQuality(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  67. const scoreServiceQuality = e.detail?.value ?? 0;
  68. this.setData({ scoreServiceQuality }, () => this._updateCanPublish());
  69. },
  70. onScoreAttitude(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  71. const scoreAttitude = e.detail?.value ?? 0;
  72. this.setData({ scoreAttitude }, () => this._updateCanPublish());
  73. },
  74. onScoreEnvironment(e: WechatMiniprogram.CustomEvent<{ value: number }>) {
  75. const scoreEnvironment = e.detail?.value ?? 0;
  76. this.setData({ scoreEnvironment }, () => this._updateCanPublish());
  77. },
  78. onContentInput(e: WechatMiniprogram.Input) {
  79. const content = e.detail?.value ?? "";
  80. this.setData({ content });
  81. },
  82. onChooseMedia() {
  83. const current = this.data.mediaList.length;
  84. if (current >= 9) {
  85. wx.showToast({ title: "图片和视频总数不能超过9个", icon: "none" });
  86. return;
  87. }
  88. const remain = 9 - current;
  89. wx.chooseMedia({
  90. count: remain,
  91. mediaType: ["image", "video"],
  92. sourceType: ["album", "camera"],
  93. maxDuration: 30,
  94. camera: "back",
  95. success: (res) => {
  96. const list = res.tempFiles.map((f) => ({
  97. path: f.tempFilePath,
  98. type: (f.fileType === "video" ? "video" : "image") as "image" | "video",
  99. }));
  100. const oldLength = this.data.mediaList.length;
  101. const next = [...this.data.mediaList, ...list].slice(0, 9);
  102. this.setData({ mediaList: next });
  103. // 选取本地媒体后,调用上传接口上传到服务器
  104. list.forEach((item, idx) => {
  105. const index = oldLength + idx;
  106. upload<string, any>({
  107. params: { name: "file", file: item.path },
  108. transform({ data }: any): string {
  109. return (data as any)?.url || (data as any);
  110. },
  111. }).then(
  112. (url) => {
  113. const key = `mediaList[${index}].path`;
  114. this.setData({ [key]: url });
  115. },
  116. (error: any) => {
  117. wx.showToast({
  118. title: error?.errMsg || "上传失败",
  119. icon: "none",
  120. });
  121. const mediaList = this.data.mediaList.filter((_, i) => i !== index);
  122. this.setData({ mediaList });
  123. }
  124. );
  125. });
  126. },
  127. });
  128. },
  129. onRemoveMedia(e: WechatMiniprogram.TouchEvent) {
  130. const index = e.currentTarget.dataset.index as number;
  131. const mediaList = this.data.mediaList.filter((_, i) => i !== index);
  132. this.setData({ mediaList });
  133. },
  134. onPreviewImage(e: WechatMiniprogram.TouchEvent) {
  135. const url = e.currentTarget.dataset.url as string;
  136. const urls = this.data.mediaList.filter((m) => m.type === "image").map((m) => m.path);
  137. if (url && urls.length) {
  138. wx.previewImage({ current: url, urls });
  139. }
  140. },
  141. onPreviewVideo(e: WechatMiniprogram.TouchEvent) {
  142. const index = e.currentTarget.dataset.index as number;
  143. const videoContext = wx.createVideoContext("offline-video-" + index, this);
  144. videoContext.requestFullScreen({});
  145. },
  146. /** 点击图片/视频:原生全屏预览(类似 test 页) */
  147. onPreviewMedia(e: WechatMiniprogram.TouchEvent) {
  148. const index = e.currentTarget.dataset.index as number;
  149. const { mediaList } = this.data;
  150. if (index < 0 || index >= mediaList.length) return;
  151. const sources = mediaList.map((m) => ({
  152. url: m.path,
  153. type: m.type as "image" | "video",
  154. }));
  155. const previewMedia = (wx as any).previewMedia as
  156. | ((option: { sources: { url: string; type: "image" | "video" }[]; current: number }) => void)
  157. | undefined;
  158. if (typeof previewMedia === "function") {
  159. previewMedia({ sources, current: index });
  160. return;
  161. }
  162. // 低版本兜底:图片用 previewImage,视频用 requestFullScreen
  163. const current = mediaList[index];
  164. if (current.type === "image") {
  165. const urls = mediaList.filter((m) => m.type === "image").map((m) => m.path);
  166. wx.previewImage({ current: current.path, urls });
  167. return;
  168. }
  169. const ctx = wx.createVideoContext("offline-video-" + index, this);
  170. ctx.requestFullScreen({});
  171. },
  172. onVideoFullscreenChange(e: WechatMiniprogram.VideoFullScreenChange) {
  173. const fullScreen = !!(e.detail && e.detail.fullScreen);
  174. this.setData({ videoFullscreen: fullScreen });
  175. },
  176. onRemoveService() {
  177. this.setData({
  178. service: {} as OfflineEvaluateModel,
  179. });
  180. },
  181. async onPublish() {
  182. if (!this.data.canPublish) {
  183. wx.showToast({ title: "请完成三项评分", icon: "none" });
  184. return;
  185. }
  186. console.log(this.data.service, "this.data.service===");
  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. console.log(data, "data===");
  200. wx.showLoading({ title: "发布中..." });
  201. await evaluateOrderGoodsMethod(data);
  202. wx.hideLoading();
  203. wx.showToast({ title: "发布成功", icon: "success" });
  204. wx.redirectTo({
  205. url: `/module/care/pages/care/verifyRecord?id=${this.data.service?.patientConditioningProgramId}`,
  206. });
  207. } catch (error: any) {
  208. wx.hideLoading();
  209. wx.showToast({ title: error.errMsg || "发布失败", icon: "none" });
  210. }
  211. },
  212. });