addAndEdit.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. <template>
  2. <div v-loading="loading">
  3. <el-form
  4. ref="form"
  5. :model="form"
  6. :rules="rules"
  7. label-width="80px"
  8. :disabled="dlgType === 3"
  9. >
  10. <el-form-item label="问题分类" prop="categoryId">
  11. <SelectRemote
  12. url="/question/category/list"
  13. field="name"
  14. v-model="form.categoryId"
  15. :selectObj="selectObj"
  16. :searchParams="searchParams"
  17. />
  18. </el-form-item>
  19. <el-form-item label="问题类型" prop="type">
  20. <el-radio-group v-model="form.type" @input="changeType">
  21. <el-radio label="1">单选</el-radio>
  22. <el-radio label="2">多选</el-radio>
  23. </el-radio-group>
  24. </el-form-item>
  25. <el-form-item label="问题描述" prop="descripiton">
  26. <el-input
  27. type="textarea"
  28. :rows="4"
  29. v-model="form.descripiton"
  30. placeholder="请输入问题描述"
  31. />
  32. </el-form-item>
  33. <el-form-item label="选项列表" prop="itemList">
  34. <el-button
  35. type="primary"
  36. @click="addOption"
  37. style="margin-bottom: 6px"
  38. v-if="dlgType !== 3"
  39. >添加选项</el-button
  40. >
  41. <el-table :data="form.itemList" style="width: 100%">
  42. <el-table-column prop="code" label="选项" width="80" align="center" />
  43. <el-table-column prop="optVal" label="值" align="center" />
  44. <el-table-column
  45. label="操作"
  46. width="120"
  47. align="center"
  48. v-if="dlgType !== 3"
  49. >
  50. <template #default="{ row }">
  51. <el-button type="text" size="small" @click="editOption(row)"
  52. >修改</el-button
  53. >
  54. <el-button type="text" size="small" @click="deleteOption(row)"
  55. >删除</el-button
  56. >
  57. </template>
  58. </el-table-column>
  59. </el-table>
  60. </el-form-item>
  61. <el-form-item label="正确选项" prop="correctItem">
  62. <!-- value-key="code" -->
  63. <el-select
  64. ref="selectRef"
  65. :multiple="form.type === '2'"
  66. v-model="form.correctItem"
  67. placeholder="请选择正确选项"
  68. style="width: 100%"
  69. >
  70. <!-- :label="`${item.code} - ${item.value}`" -->
  71. <el-option
  72. v-for="item in form.itemList"
  73. :key="item.code"
  74. :label="item.code"
  75. :value="item.code"
  76. ></el-option>
  77. </el-select>
  78. </el-form-item>
  79. <el-form-item label="问题解析" prop="analysis">
  80. <el-input
  81. type="textarea"
  82. :rows="4"
  83. v-model="form.analysis"
  84. placeholder="请输入问题解析"
  85. />
  86. </el-form-item>
  87. <el-form-item label="备注" prop="remark">
  88. <el-input
  89. type="textarea"
  90. :rows="4"
  91. v-model="form.remark"
  92. placeholder="请输入备注"
  93. />
  94. </el-form-item>
  95. </el-form>
  96. <div style="text-align: right" v-if="dlgType !== 3">
  97. <el-button type="primary" @click="handleConfirm">确 定</el-button>
  98. <el-button @click="handleCancel">取 消</el-button>
  99. </div>
  100. <div style="text-align: right" v-else>
  101. <el-button @click="handleCancel">关 闭</el-button>
  102. </div>
  103. <!-- 新增/编辑选项框 -->
  104. <el-dialog
  105. :title="dlgTitle"
  106. :visible.sync="optionVisible"
  107. width="30%"
  108. append-to-body
  109. >
  110. <el-form
  111. ref="optionForm"
  112. :model="optionForm"
  113. :rules="optionRules"
  114. label-width="80px"
  115. >
  116. <el-form-item label="选项">
  117. <el-input v-model="optionForm.code" disabled />
  118. </el-form-item>
  119. <el-form-item label="值" prop="optVal">
  120. <el-input
  121. type="textarea"
  122. :rows="4"
  123. v-model="optionForm.optVal"
  124. placeholder="请输入选项值"
  125. />
  126. </el-form-item>
  127. </el-form>
  128. <span slot="footer" class="dialog-footer">
  129. <el-button type="primary" @click="confirmOption">确 定</el-button>
  130. <el-button @click="optionVisible = false">取 消</el-button>
  131. </span>
  132. </el-dialog>
  133. </div>
  134. </template>
  135. <script>
  136. import SelectRemote from "@/components/SelectRemote";
  137. export default {
  138. components: { SelectRemote },
  139. props: {
  140. data: {
  141. type: Object,
  142. default: () => {},
  143. },
  144. loading: {
  145. type: Boolean,
  146. default: false,
  147. },
  148. dlgType: {
  149. // 弹窗类型 1 - 新增 2 - 修改 3 - 查看
  150. type: Number,
  151. default: 1,
  152. },
  153. },
  154. data() {
  155. return {
  156. // 选中的问题分类
  157. selectObj: {},
  158. // 远程搜索框的查询条件
  159. searchParams: {},
  160. // 选项弹窗相关参数
  161. dlgTitle: "",
  162. optionVisible: false,
  163. optionForm: {},
  164. optionRules: {
  165. optVal: [
  166. { required: true, trigger: "blur", message: "选项值不能为空" },
  167. ],
  168. },
  169. form: {
  170. categoryId: "",
  171. type: "1",
  172. descripiton: "",
  173. itemList: [],
  174. correctItem: "",
  175. analysis: "",
  176. remark: "",
  177. },
  178. rules: {
  179. categoryId: [
  180. { required: true, trigger: "change", message: "请选择问题分类" },
  181. ],
  182. descripiton: [
  183. { required: true, trigger: "blur", message: "请输入问题描述" },
  184. ],
  185. itemList: [{ required: true, trigger: "blur", message: "请添加选项" }],
  186. correctItem: [
  187. { required: true, trigger: "change", message: "请选择正确选项" },
  188. ],
  189. analysis: [
  190. { required: true, trigger: "blur", message: "请输入问题解析" },
  191. ],
  192. },
  193. };
  194. },
  195. watch: {
  196. data: {
  197. handler(newVal) {
  198. if (newVal) {
  199. this.form = {
  200. id: newVal.id || "",
  201. categoryId: newVal.categoryId || "",
  202. type: newVal.type || "1",
  203. descripiton: newVal.descripiton || "",
  204. itemList: newVal.itemList ? JSON.parse(newVal.itemList) : [],
  205. correctItem: newVal.correctItem
  206. ? newVal.type === "1"
  207. ? newVal.correctItem
  208. : newVal.correctItem.split(",")
  209. : "",
  210. analysis: newVal.analysis || "",
  211. remark: newVal.remark || "",
  212. };
  213. this.selectObj = {
  214. id: newVal.categoryId || "",
  215. selectLabel: newVal.categoryName || "",
  216. };
  217. this.$nextTick(() => {
  218. this.$refs.form && this.$refs.form.clearValidate();
  219. });
  220. }
  221. },
  222. },
  223. },
  224. methods: {
  225. // 切换单选多选
  226. changeType(val) {
  227. console.log(this.form.correctItem);
  228. // console.log(val, this.form.correctItem, this.$refs.selectRef);
  229. if (val === "2") {
  230. this.form.correctItem = [];
  231. this.$refs.selectRef.selectedLabel = "";
  232. } else {
  233. this.form.correctItem = undefined;
  234. }
  235. this.$nextTick(() => {
  236. this.$refs.form && this.$refs.form.clearValidate();
  237. });
  238. },
  239. // 确认添加选项
  240. confirmOption() {
  241. this.$refs.optionForm.validate((valid) => {
  242. if (valid) {
  243. if (this.dlgTitle === "编辑选项") {
  244. let targetIndex = this.form.itemList.findIndex(
  245. (item) => item.code === this.optionForm.code
  246. );
  247. this.$set(this.form.itemList, targetIndex, this.optionForm);
  248. } else {
  249. this.form.itemList.push(this.optionForm);
  250. }
  251. this.optionVisible = false;
  252. }
  253. });
  254. },
  255. // 删除选项(需要更新一下code值)
  256. deleteOption(row) {
  257. console.log("删除的当前行数据", row);
  258. let targetIndex = this.form.itemList.findIndex(
  259. (item) => item.code === row.code
  260. );
  261. // 先判断一下删除的选项是否被选中为正确选项
  262. // 是的话 需要确认是否删除
  263. if (this.form.correctItem.includes(row.code)) {
  264. this.$modal
  265. .confirm("当前选项已被选中为正确选项,是否确认删除?")
  266. .then(() => {
  267. this.form.itemList.splice(targetIndex, 1);
  268. // 清除正确选项
  269. this.form.correctItem = this.form.type === "1" ? "" : [];
  270. // 更新选项列表的code
  271. this.form.itemList.forEach((item, index) => {
  272. item.code = String.fromCharCode(index + 65);
  273. });
  274. })
  275. .catch(() => {});
  276. } else {
  277. this.form.itemList.splice(targetIndex, 1);
  278. // 更新选项列表的code
  279. this.form.itemList.forEach((item, index) => {
  280. item.code = String.fromCharCode(index + 65);
  281. });
  282. }
  283. },
  284. // 编辑选项
  285. editOption(row) {
  286. console.log("编辑的当前行数据", row);
  287. this.dlgTitle = "编辑选项";
  288. this.optionVisible = true;
  289. this.optionForm = { ...row };
  290. },
  291. // 添加选项
  292. addOption() {
  293. // 首先拿到选项列表的最后一项的code,然后根据这个code生成下一项的code
  294. // 也可以拿到选项列表的长度,根据长度判断下一个的code, A ---- 65
  295. let index = this.form.itemList.length;
  296. let nextCode = String.fromCharCode(index + 65);
  297. console.log("下一项的code", nextCode);
  298. this.dlgTitle = "新增选项";
  299. this.optionVisible = true;
  300. this.optionForm = { code: nextCode, optVal: "" };
  301. // 清除一下校验
  302. this.$refs.optionForm && this.$refs.optionForm.clearValidate();
  303. },
  304. // 确定
  305. handleConfirm() {
  306. this.$refs.form.validate((valid) => {
  307. if (valid) {
  308. let obj = {
  309. ...this.form,
  310. itemList: JSON.stringify(this.form.itemList),
  311. correctItem:
  312. this.form.type === "1"
  313. ? this.form.correctItem
  314. : this.sortEn(this.form.correctItem).join(","),
  315. };
  316. console.log(obj);
  317. this.$emit("confirm", obj);
  318. }
  319. });
  320. },
  321. // 数组的值按照英文字母排序
  322. sortEn(arr) {
  323. arr.sort(function (a, b) {
  324. return a.charCodeAt(0).toString(16) - b.charCodeAt(0).toString(16);
  325. });
  326. return arr;
  327. },
  328. // 取消
  329. handleCancel() {
  330. this.form = {
  331. categoryId: "",
  332. type: "1",
  333. descripiton: "",
  334. itemList: [],
  335. correctItem: "",
  336. analysis: "",
  337. remark: "",
  338. };
  339. this.$nextTick(() => {
  340. this.$refs.form && this.$refs.form.clearValidate();
  341. });
  342. this.$emit("cancel");
  343. },
  344. },
  345. };
  346. </script>
  347. <style lang="scss" scoped></style>