index.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <CollapseContainer
  3. class="sys-container"
  4. title="系统配置"
  5. :canExpan="false"
  6. helpMessage="可以在此增改系统的变量和分组,也可以自定义分组和变量"
  7. >
  8. <a-button
  9. v-for="(group, index) in groupList"
  10. :key="index"
  11. type="default"
  12. class="mr-2"
  13. :class="current_index === index ? 'current-btn' : ''"
  14. @click="handleGroupBtn(group, index)"
  15. >
  16. {{ group }}
  17. </a-button>
  18. <a-button
  19. preIcon="bx:bx-plus-medical"
  20. @mouseenter="showTip"
  21. @mouseleave="hideTip"
  22. @click="addConfig"
  23. class="mr-2"
  24. />
  25. <span v-if="tipShow" class="tip">点击添加新的配置</span>
  26. <BasicTable ref="tableRef" :canResize="true" v-if="tableShow" @register="registerTable">
  27. <template #action="{ record, column }">
  28. <TableAction :actions="createActions(record, column)" stopButtonPropagation />
  29. </template>
  30. </BasicTable>
  31. <BasicForm
  32. class="config-form"
  33. v-if="formShow"
  34. @register="registerForm"
  35. @submit="handleFormSubmit"
  36. />
  37. <div v-if="tableShow" class="actions">
  38. <a-button class="mr-2" type="default" @click="handleTableReset">
  39. {{ t('common.resetText') }}
  40. </a-button>
  41. <a-button class="mr-2" type="primary" @click="handleTableSubmit">
  42. {{ t('common.submitText') }}
  43. </a-button>
  44. </div>
  45. </CollapseContainer>
  46. </template>
  47. <script lang="ts">
  48. import { useMessage } from '/@/hooks/web/useMessage';
  49. import { defineComponent, nextTick, reactive, ref, toRefs, unref } from 'vue';
  50. import { CollapseContainer } from '/@/components/Container/index';
  51. import { BasicForm, useForm } from '/@/components/Form/index';
  52. import { schemas } from './data';
  53. import { useI18n } from '/@/hooks/web/useI18n';
  54. import { adapt } from '/@/utils/adapt';
  55. import { validateType } from '/@/utils/validTools';
  56. import { useAppStore } from '/@/store/modules/app';
  57. import {
  58. BasicTable,
  59. useTable,
  60. TableAction,
  61. ActionItem,
  62. EditRecordRow,
  63. TableActionType,
  64. } from '/@/components/Table';
  65. import {
  66. getConfigGroup,
  67. getConfigInfo,
  68. addConfigInfo,
  69. editConfigInfo,
  70. deleteConfigInfo,
  71. } from '/@/api/sys/general';
  72. import { columns } from './data';
  73. export default defineComponent({
  74. name: 'Config',
  75. components: { CollapseContainer, BasicTable, BasicForm, TableAction },
  76. setup() {
  77. const { t } = useI18n();
  78. const { createMessage } = useMessage();
  79. const appStore = useAppStore();
  80. const { success /*, error */ } = createMessage;
  81. const tableHeight = adapt().tableHeight;
  82. const state = reactive({
  83. tipShow: false,
  84. tableShow: true,
  85. formShow: false,
  86. groupList: [] as object[],
  87. group: 'basic',
  88. current_index: 0,
  89. });
  90. const tableRef = ref<Nullable<TableActionType>>(null);
  91. const [registerTable] = useTable({
  92. columns: columns,
  93. maxHeight: tableHeight,
  94. api: getConfigInfo,
  95. afterFetch: afterFetch,
  96. actionColumn: {
  97. width: 160,
  98. // title: '操作',
  99. dataIndex: 'action',
  100. slots: { customRender: 'action' },
  101. fixed: undefined,
  102. },
  103. showIndexColumn: false,
  104. pagination: false,
  105. });
  106. const [
  107. registerForm,
  108. // { validateFields, clearValidate, getFieldsValue, resetFields, setFieldsValue },
  109. ] = useForm({
  110. labelWidth: 120,
  111. schemas,
  112. actionColOptions: {
  113. span: 24,
  114. },
  115. showActionButtonGroup: true,
  116. });
  117. function getTableAction() {
  118. // 获取组件
  119. const tableAction = unref(tableRef);
  120. if (!tableAction) {
  121. throw new Error('tableAction is null');
  122. }
  123. return tableAction;
  124. }
  125. // 处理请求数据
  126. function afterFetch(result) {
  127. result = result[state.group].list;
  128. console.log(`config result`, result);
  129. if (result[0].title === 'Site name') {
  130. appStore.setAppTitle(result[0].value);
  131. }
  132. if (result[1].title === 'Logo') {
  133. appStore.setAppLogo(result[1].value);
  134. }
  135. return result;
  136. }
  137. getGroupList();
  138. async function getGroupList() {
  139. const res = await getConfigGroup();
  140. state.groupList = Object.values(res.group);
  141. }
  142. function showTip() {
  143. state.tipShow = true;
  144. }
  145. function hideTip() {
  146. state.tipShow = false;
  147. }
  148. async function handleGroupBtn(group, i) {
  149. state.tableShow = true;
  150. state.formShow = false;
  151. state.current_index = i;
  152. await nextTick();
  153. getTableAction().reload();
  154. state.group = group.toLowerCase();
  155. }
  156. function addConfig() {
  157. state.tableShow = false;
  158. state.formShow = true;
  159. }
  160. function handleTableReset() {
  161. getTableAction().reload();
  162. }
  163. async function handleTableSubmit() {
  164. const data = getTableAction().getDataSource();
  165. let flag = true;
  166. data.map((item) => {
  167. if (item.rule && item.type !== 'array') {
  168. const rule = item.rule.split(',');
  169. const res = validateType(rule, item.value);
  170. item.errMsg = res.errMsg;
  171. if (!res.isValid) {
  172. flag = res.isValid;
  173. }
  174. }
  175. });
  176. if (flag) {
  177. const params = {};
  178. data.map((item) => {
  179. if (item.type === 'array') {
  180. params[item.name] = JSON.stringify(item.value);
  181. console.log(`item`, item);
  182. console.log(`item.value`, item.value);
  183. } else {
  184. if (item.type === 'selects' || item.type === 'checkbox') {
  185. params[item.name] = item.value.toString();
  186. } else {
  187. params[item.name] = item.value;
  188. }
  189. }
  190. });
  191. await editConfigInfo(params).then(() => {
  192. getTableAction().reload();
  193. success('修改成功!');
  194. });
  195. } else {
  196. console.log('======未通过校验====');
  197. }
  198. }
  199. async function handleFormSubmit(e) {
  200. if (!e.rule) {
  201. e.rule = '';
  202. } else {
  203. e.rule = e.rule.toString();
  204. }
  205. await addConfigInfo(e).then(() => {
  206. success('创建成功!');
  207. handleGroupBtn('Basic', 0); // 跳转显示到table基础配置
  208. });
  209. }
  210. async function handleDelete(record: Recordable) {
  211. await deleteConfigInfo({ id: record.id }).then(() => {
  212. getTableAction().reload();
  213. success('删除成功!');
  214. });
  215. }
  216. function createActions(record: EditRecordRow): ActionItem[] {
  217. if (record.id <= 9) {
  218. return [];
  219. }
  220. return [
  221. {
  222. label: '',
  223. color: 'error',
  224. icon: 'ic:outline-delete-outline',
  225. popConfirm: {
  226. title: '是否确认删除',
  227. confirm: handleDelete.bind(null, record),
  228. },
  229. },
  230. ];
  231. }
  232. return {
  233. t,
  234. createActions,
  235. tableRef,
  236. registerTable,
  237. registerForm,
  238. showTip,
  239. hideTip,
  240. handleGroupBtn,
  241. addConfig,
  242. handleTableReset,
  243. handleTableSubmit,
  244. handleFormSubmit,
  245. ...toRefs(state),
  246. };
  247. },
  248. });
  249. </script>
  250. <style>
  251. .sys-container {
  252. position: relative;
  253. }
  254. .vben-collapse-container__body > .mr-2 {
  255. margin-top: 5px;
  256. font-weight: 550 !important;
  257. }
  258. .tip {
  259. position: absolute;
  260. top: 30px;
  261. padding: 3px 6px;
  262. color: #fff;
  263. background-color: black;
  264. border-radius: 3px;
  265. }
  266. .config-form {
  267. margin-top: 10px;
  268. }
  269. .ant-form-item-children {
  270. display: flex;
  271. justify-content: center;
  272. }
  273. .upload-btn {
  274. bottom: 0 !important;
  275. }
  276. /* .current-btn {
  277. color: #3785cc;
  278. border: 1px solid #3785cc;
  279. } */
  280. </style>