Detail.cshtml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. 
  2. @using WeOnlineApp.Configuration
  3. @using WeOnlineApp.Views.Shared.Modals
  4. @model WeOnlineApp.Question.Dto.QuestionDto
  5. @{
  6. Layout = "~/Views/Shared/Layout/_Layout.Play.cshtml";
  7. ViewBag.Title = "问题详情";
  8. bool isAnswer = Model.QuestionState == QuestionStateDefinition.Answer;
  9. }
  10. @Html.Partial("~/Views/Play/_BoxBaseStyle.cshtml")
  11. <style>
  12. .select-answer {
  13. font-weight: 600;
  14. color: #049e9a;
  15. border-color: #049e9a;
  16. }
  17. .box {
  18. width: 100%;
  19. height: calc(100vh - 20px);
  20. position: relative;
  21. }
  22. .answer-box {
  23. border: 2px solid var(--mainColor);
  24. margin: 15px 0;
  25. border-radius: 5px;
  26. position: relative;
  27. }
  28. .answer-box .answer-box {
  29. border-style: dotted;
  30. margin: 10px;
  31. }
  32. .answer-box .text {
  33. padding: 5px 10px;
  34. word-break: break-all;
  35. min-height: 60px;
  36. display: flex;
  37. align-items: center;
  38. }
  39. .answer-box .tool {
  40. border-top: 1px solid var(--mainColor);
  41. padding: 5px 10px;
  42. display: flex;
  43. align-items: center;
  44. justify-content: space-between;
  45. }
  46. .answer-box .tool:not(:last-child) {
  47. border-bottom: 1px solid var(--mainColor);
  48. }
  49. .answer-box .answer-box .tool {
  50. border-top-style: dotted;
  51. }
  52. .answer-box .answer-box .tool:not(:last-child) {
  53. border-bottom-style: dotted;
  54. }
  55. .answer-box .tool .name {
  56. font-size: 14px;
  57. color: #666;
  58. }
  59. .answer-box .tool .name strong {
  60. color: var(--mainColor);
  61. font-size: 16px;
  62. }
  63. .answer-box .tool .btn {
  64. padding: 3px 8px;
  65. font-size: 12px;
  66. margin: 0 5px;
  67. }
  68. .more-box {
  69. width: 100%;
  70. height: 200px;
  71. background: linear-gradient(rgba(255, 255, 255, .8), rgba(255, 255, 255, 1));
  72. position: absolute;
  73. bottom: 0;
  74. display: flex;
  75. justify-content: center;
  76. align-items: center;
  77. }
  78. .has-answer {
  79. position: absolute;
  80. font-size: 20px;
  81. padding: 5px 10px;
  82. color: red;
  83. border: 3px solid red;
  84. opacity: 0.5;
  85. top: calc(50% - 20px);
  86. left: calc(50% - 35px);
  87. margin: 0 auto;
  88. transform: rotateZ(-25deg);
  89. z-index: 2;
  90. }
  91. </style>
  92. <div style="padding: 0 15px;" >
  93. <div class="row">
  94. <div class="col-sm-5">
  95. <div class="box">
  96. <div class="box-header">
  97. <span>问题详情</span>
  98. <div class="back-btn" style="left: 20px; right: auto">
  99. @if (Model.CreatorUserId != AbpSession.UserId)
  100. {
  101. if (Model.IsFavorite)
  102. {
  103. <button type="button" class="btn btn-danger btn-sm" style="width: 80px;" onclick="Favorite(this, false)">取消收藏</button>
  104. }
  105. else
  106. {
  107. <button type="button" class="btn btn-success btn-sm" style="width: 80px;" onclick="Favorite(this, true)">收藏问题</button>
  108. }
  109. }
  110. </div> <div class="back-btn">
  111. @if (!isAnswer)
  112. {
  113. <button type="button" class="btn btn-outline-success btn-sm" style="width: 80px;" onclick="Answer('')">我要答疑</button>
  114. }
  115. <button type="button" class="btn btn-outline-light btn-sm" style="width: 80px;" onclick="Back()">返回课程</button>
  116. </div>
  117. </div>
  118. <div class="box-body scroll">
  119. <dl class="dl">
  120. <dt>问题标题:</dt>
  121. <dd>@Model.Title</dd>
  122. </dl>
  123. <dl class="dl">
  124. <dt>问题详情:</dt>
  125. <dd id="has-answer-box" style="position: relative">
  126. @Model.ContentInfo
  127. @if (isAnswer)
  128. {
  129. <div class="has-answer">已解答</div>
  130. }
  131. </dd>
  132. </dl>
  133. @if (Model.Camp != null)
  134. {
  135. <dl class="dl">
  136. <dt>课程名称:</dt>
  137. <dd>@Model.Camp.Name</dd>
  138. </dl>
  139. <dl class="dl">
  140. <dt>课程主题:</dt>
  141. <dd>@Model.Camp.PackageName</dd>
  142. </dl>
  143. <dl class="dl">
  144. <dt>课程目标:</dt>
  145. <dd>@Model.Camp.Purposes</dd>
  146. </dl>
  147. <dl class="dl">
  148. <dt>课程积分:</dt>
  149. <dd>@Model.Camp.SubjectPoint 分</dd>
  150. </dl>
  151. }
  152. </div>
  153. </div>
  154. </div>
  155. <div class="col-sm-7">
  156. <div class="box">
  157. <div class="box-header">
  158. <span>答疑详情</span>
  159. <div class="back-btn">
  160. @*<button type="button" class="btn btn-outline-light btn-sm" style="width: 80px;" onclick="Back()">返回课程</button>*@
  161. </div>
  162. </div>
  163. <div class="box-body scroll" style="padding-bottom: 0">
  164. <div id="answer-box" style="position: relative">
  165. @if (Model.Answers != null && Model.Answers.Any())
  166. {
  167. foreach (var a in Model.Answers)
  168. {
  169. var isAnswer2 = isAnswer && a.AnswerState == AnswerStateDefinition.Answer;
  170. <div class="answer-box" id="qa-@(a.Id)">
  171. @if (isAnswer2)
  172. {
  173. <div class="has-answer">已采纳</div>
  174. }
  175. <div class="text">@(a.ContentInfo)</div>
  176. <div class="tool">
  177. <div class="name">
  178. <strong>@(a.RealName)</strong>&nbsp;&nbsp;@(a.CreationTime.ToString("yyyy-MM-dd HH:mm:ss"))
  179. </div>
  180. <div class="btn-box">
  181. @if (!isAnswer && Model.CreatorUserId == AbpSession.UserId && a.UserName != AbpSession.UserName)
  182. {
  183. <button type="button" class="select-answer btn btn-outline-info btn-sm" onclick="SelectAnswer('@(a.Id)')">采纳答疑</button>
  184. }
  185. @if (a.ChildrenCount > 0)
  186. {
  187. <button type="button" class="btn btn-info btn-sm" data-type="2" onclick="QueryAnswer(this, '@(a.Id)')">查看回复(@(a.ChildrenCount))</button>
  188. }
  189. @if (!isAnswer)
  190. {
  191. <button type="button" class="btn btn-info btn-sm" onclick="Answer('@(a.Id)')">回复答疑</button>
  192. }
  193. </div>
  194. </div>
  195. </div>
  196. }
  197. if (Model.Answers.Count == IwbConsts.AnswerTakeCount)
  198. {
  199. <div class="more-box">
  200. <button type="button" class="btn btn-danger" data-type="1" onclick="QueryAnswer(this, '', '@(Model.Id)')">查看更多</button>
  201. </div>
  202. }
  203. }
  204. </div>
  205. </div>
  206. </div>
  207. </div>
  208. </div>
  209. </div>
  210. @section modal
  211. {
  212. @{
  213. var modal2 = new ModalViewModel("我要答疑", "", new ModalBodyViewModel(new List<Input>()
  214. {
  215. new InputHide("id"),
  216. new InputHide("questionNo"),
  217. new InputHide("answerNo"),
  218. new Input("campName", "课程名称",placeholder:"未选择课程").SetNotRequired().SetDisabled(),
  219. new Input("title", "问题标题").SetDisabled(),
  220. new InputTextarea("contentInfo", "答疑内容"),
  221. }, "form-a"), "modal-a");
  222. }
  223. @Html.Partial("Modals/_Modal", modal2)
  224. }
  225. @section scripts
  226. {
  227. <script>
  228. $(function() {
  229. OverlayScrollbar($('.scroll'));
  230. });
  231. function Back() {
  232. window.location.href = "@Url.Action("PlayList", "Play")";
  233. }
  234. function Answer(answerNo) {
  235. OpenModal({
  236. url: abp.appUrl + "Question/AddAnswer",
  237. modal: "modal-a",
  238. data: {
  239. questionNo: '@(Model.Id)',
  240. answerNo: answerNo,
  241. title: '@(Model.Title)',
  242. campName: '@(Model.Camp == null ? "" : Model.CampName)'
  243. },
  244. success: function(res) {
  245. var str = AnswerFormatter(res, 1);
  246. if (answerNo) {
  247. $('#qa-' + answerNo + '>.tool').after(str);
  248. } else {
  249. $('#answer-box').prepend(str);
  250. }
  251. }
  252. });
  253. }
  254. function SelectAnswer(no) {
  255. $.iwbAjax4({
  256. url: abp.appUrl + "Question/SelectAnswer",
  257. data: { id: '@(Model.Id)', answerNo:no},
  258. success: function() {
  259. $('#has-answer-box').append('<div class="has-answer">已解答</div>');
  260. $('#qa-' + no).append('<div class="has-answer">已采纳</div>');
  261. $('.select-answer').remove();
  262. }
  263. });
  264. }
  265. function Favorite(that,favorite) {
  266. $.iwbAjax4({
  267. url: abp.appUrl + "Question/Favorite",
  268. data: { id: '@(Model.Id)', isFavorite: favorite },
  269. success: function () {
  270. if (favorite) {
  271. $(that).removeClass('btn-success').addClass('btn-danger').text('取消收藏');
  272. } else {
  273. $(that).removeClass('btn-danger').addClass('btn-success').text('收藏问题');
  274. }
  275. abp.message.success(favorite?'收藏成功':'取消成功', "收藏问题");
  276. }
  277. });
  278. }
  279. function QueryAnswer(that, answerNo, questionNo) {
  280. var skip , take = 5;
  281. var type = $(that).data('type');
  282. var $that = type == 1 ? $('#answer-box') : $(that).closest('.answer-box');
  283. skip = $that.children('.answer-box').length;
  284. $.iwbAjax4({
  285. url: abp.appUrl + "Question/GetChildAnswer",
  286. data: { questionNo: questionNo, answerNo: answerNo, skip: skip, take: take },
  287. success: function(res) {
  288. if (type == 2) {
  289. $(that).remove();
  290. type = 3;
  291. }
  292. $that.children('.more-box').remove();
  293. var str = AnswersFormatter(res, type);
  294. if (str) {
  295. if (type == 1) {
  296. $('#answer-box').append(str);
  297. } else {
  298. $('#qa-' + answerNo).append(str);
  299. }
  300. }
  301. if (res && res.length == take) {
  302. str =
  303. '<div class="more-box"><button type="button" data-type="{0}" class="btn btn-danger" onclick="QueryAnswer(this,\'{1}\',\'{2}\')">查看更多</button></div>'
  304. .format(type, answerNo, questionNo);
  305. $that.append(str);
  306. }
  307. }
  308. });
  309. }
  310. function AnswersFormatter(data, type) {
  311. var str = '';
  312. if (data && data.length) {
  313. data.forEach(function(v) {
  314. str += AnswerFormatter(v, type);
  315. });
  316. }
  317. return str;
  318. }
  319. function AnswerFormatter(data, type) {
  320. var str = '';
  321. if (data) {
  322. str += '<div class="answer-box" id="qa-{0}">'.format(data.id);
  323. str += '<div class="text">{0}</div>'.format(data.contentInfo);
  324. str += '<div class="tool">';
  325. str += '<div class="name"><strong>{0}</strong>&nbsp;&nbsp;{1}</div>'.format(data.realName,new Date
  326. (data.creationTime).format("yyyy-MM-dd hh:mm:ss"));
  327. str += '<div class="btn-box">';
  328. if (type == 1 &&
  329. data.UserName != '@(AbpSession.UserName)' &&
  330. data.questionState == @(QuestionStateDefinition.New)) {
  331. str +=
  332. '<button type="button" class="select-answer btn btn-outline-info btn-sm" onclick="SelectAnswer(\'{0}\')">采纳答疑</button>'
  333. .format(data.id);
  334. }
  335. str += data.childrenCount > 0
  336. ? '<button type="button" class="btn btn-info btn-sm" data-type="2" onclick="QueryAnswer(this,\'{0}\')">查看回复({1})</button>'
  337. .format(data.id, data.childrenCount)
  338. : '';
  339. str += '<button type="button" class="btn btn-info btn-sm" onclick="Answer(\'{0}\')">回复答疑</button>'
  340. .format(data.id);
  341. str += '</div>';
  342. str += '</div>';
  343. str += '</div>';
  344. }
  345. return str;
  346. }
  347. </script>
  348. }