feat:回答管理页面搭建

This commit is contained in:
李想 2025-03-19 14:46:58 +08:00
parent 3161d538b5
commit 8b80578d99
8 changed files with 432 additions and 19 deletions

View File

@ -87,7 +87,7 @@ export default {
},
},
},
emits: ['focus', 'blur', 'change'],
emits: ['focus', 'blur', 'change', 'update:value'],
setup(props, cxt) {
const refEditor = shallowRef();
const valueHtml = ref('');
@ -112,6 +112,7 @@ export default {
*/
const handleChange = (editor) => {
cxt.emit('change', editor);
cxt.emit('update:value', valueHtml.value);
};
/**
* 组件销毁

View File

@ -1,3 +1,7 @@
import * as redBlack from './redAndBlank';
import * as redBlackApi from './redAndBlank';
import * as materialApi from './material';
export { redBlack };
export default {
...materialApi,
...redBlackApi,
};

View File

@ -0,0 +1,9 @@
import request from '@/utils/axios';
/* 获取物资类型 */
export function getMaterailTypes(params) {
return request({
url: '/input/common/getList',
params,
});
}

View File

@ -1 +1 @@
import request from '@/utils/request';
import request from '@/utils/axios';

View File

@ -123,12 +123,12 @@ const inputSuppliesRoutes = [
component: () => import('@/views/inputSuppliesManage/redBlackRank/index.vue'),
meta: { title: '企业红黑榜', icon: 'Document' },
},
// {
// path: '/sub-government-affairs-service/knowledgeManage',
// name: 'knowledgeManage',
// component: () => import('@/views/inputSuppliesManage/knowledgeManage/index.vue'),
// meta: { title: '知识库', icon: 'Document' },
// },
{
path: '/sub-government-affairs-service/knowledgeManage',
name: 'knowledgeManage',
component: () => import('@/views/inputSuppliesManage/knowledgeManage/index.vue'),
meta: { title: '知识库', icon: 'Document' },
},
// {
// path: '/sub-government-affairs-service/patrolCaseManage',
// name: 'patrolCaseManage',

View File

@ -1,19 +1,195 @@
<template>
<CustomCard>知识库 </CustomCard>
<CustomCard>
<avue-crud
ref="curdRef"
v-model:page="pageData"
v-model:search="searchCondition"
:data="data"
:option="option"
:table-loading="_loading"
@search-change="handleSearch"
@search-reset="handleSearchReset"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
@row-save="handleRowSave"
@row-update="handleRowUpdate"
>
<template #menu="scope">
<custom-table-operate :actions="actions" :data="scope" />
</template>
<template #replyContent-form>
<custom-rich-editor v-model:value="richText" :read-only="true" />
</template>
</avue-crud>
</CustomCard>
</template>
<script setup>
import { ref } from 'vue';
import { ref, reactive, onMounted, h } from 'vue';
import CustomCard from '@/components/CustomCard.vue';
import { CRUD_OPTIONS } from '@/config';
onMounted(getData);
/* --------------- data --------------- */
// #region
const curdRef = ref();
const _loading = ref(false);
const data = ref([]);
const searchCondition = ref({
keywords: '',
status: '',
});
const option = reactive({
...CRUD_OPTIONS,
addBtn: false,
selection: false,
dialogWidth: 800,
editTitle: '回复',
column: [
{
label: '关键词',
prop: 'keywords',
hide: true,
search: true,
editDisplay: false,
viewDisplay: false,
},
{
label: '状态',
prop: 'status',
type: 'select',
hide: true,
search: true,
dicData: [
{ label: '已回复', value: '1' },
{ label: '未回复', value: '0' },
],
editDisplay: false,
viewDisplay: false,
},
{
label: '名称',
prop: 'question',
renderForm: ({ row }) => {
return h('span', {}, row.question);
},
span: 24,
},
{
label: '提问时间',
prop: 'questionDate',
viewDisplay: false,
renderForm: ({ row }) => {
return h('span', {}, row.questionDate);
},
span: 24,
},
{
label: '专家姓名',
prop: 'expertName',
editDisplay: false,
viewDisplay: false,
},
{
label: '回复时间',
prop: 'replyDate',
editDisplay: false,
viewDisplay: false,
},
{
label: '回复内容Text',
prop: 'replyContentText',
editDisplay: false,
viewDisplay: false,
},
{
hide: true,
label: '回复内容',
prop: 'replyContent',
viewDisplay: false,
span: 24,
},
],
});
const pageData = reactive({
currentPage: 1,
size: 10,
total: 0,
});
const actions = reactive([
{
name: '回复',
icon: 'view',
auth: ({ row }) => row.status == '0',
event: handleReply,
},
{
name: '详情',
icon: 'edit',
event: handleInfo,
},
]);
const richText = ref();
// #endregion
/* --------------- methods --------------- */
// #region
function getData() {
let params = Object.assign(
{
currentPage: pageData.currentPage,
size: pageData.size,
},
searchCondition.value
);
console.log('params', params);
for (let i = 0; i < 13; i++) {
data.value.push({
id: i + Date.now(),
question: '我是问题' + i,
questionDate: '2022-01-01',
expertName: '专家' + i,
replyDate: '2022-01-01',
replyContent: `<ol><li>${i}${i}${i}${i}${i}</li></ol><ul><li>😂😂</li></ul><p><strong>333</strong></p><p><span style="color: rgb(9, 109, 217);">4534</span></p>`,
status: !(i % 2) ? '0' : '1',
});
}
}
function handleSearch(form, done) {
resetGet();
done();
}
function handleSearchReset() {
resetGet();
}
function handleCurrentChange(val) {
console.log(val);
}
function handleSizeChange(val) {
console.log(val);
}
function handleRowUpdate(form, done, loading) {
console.log('rich', richText.value);
console.log('update ', form);
loading();
}
function handleRowSave(form, done, loading) {
loading();
}
function resetGet() {
pageData.currentPage = 1;
getData;
}
function handleReply({ row }) {
console.log('reply', row);
curdRef.value.rowEdit(row);
}
function handleInfo(row) {
console.log('info', row);
curdRef.value.rowView(row);
}
// #endregion
</script>

View File

@ -1,12 +1,50 @@
<template>
<section>
<CustomCard>
<!-- <section style="width: 600px; height: 400px">
<custom-rich-editor />
</section>
</section> -->
<avue-crud
ref="curdRef"
v-model:page="pageData"
:data="data"
:before-close="handleDialogClose"
:option="option"
:table-loading="_loading"
@search-change="handleSearch"
@search-reset="handleSearchReset"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
@row-save="handleRowSave"
@row-update="handleRowUpdate"
>
<template #menu="scope">
<custom-table-operate :actions="actions" :data="scope" />
</template>
</avue-crud>
</CustomCard>
</template>
<script setup>
import { ref } from 'vue';
import CustomCard from '@/components/CustomCard.vue';
import { useMaterialHook } from './useMaterialHook';
const {
curdRef,
_loading,
data,
pageData,
option,
actions,
handleDialogClose,
handleSearch,
handleRowSave,
handleRowUpdate,
handleSearchReset,
handleCurrentChange,
handleSizeChange,
} = useMaterialHook();
/* --------------- data --------------- */
// #region

View File

@ -1,12 +1,197 @@
import { ref } from 'vue';
import { ref, reactive, onMounted } from 'vue';
import { CRUD_OPTIONS } from '@/config';
import inputSuppliesApis from '@/apis/inputSuppliesApi';
const { getMaterailTypes } = inputSuppliesApis;
export const useMaterialHook = () => {
onMounted(() => {
getData();
getTypes();
});
/* ------ data ------ */
// #region
const currentType = ref('0');
const curdRef = ref();
const _loading = ref(false);
const materialTypes = reactive([
{
id: '0',
dataName: '全部',
},
]);
const pageData = ref({
currentPage: 1,
pageSize: 10,
total: 0,
});
const testData = reactive([
{ type: '1', id: 1, name: '物资1', producer: '生产厂家1', dealer: '经销商1' },
{ type: '2', id: 2, name: '物资2', producer: '生产厂家2', dealer: '经销商2' },
{ type: '3', id: 3, name: '物资3', producer: '生产厂家3', dealer: '经销商3' },
{ type: '4', id: 4, name: '物资4', producer: '生产厂家4', dealer: '经销商4' },
{ type: '5', id: 4, name: '物资4', producer: '生产厂家4', dealer: '经销商4' },
]);
const data = ref([]);
const option = reactive({
...CRUD_OPTIONS,
selection: false,
column: [
{
label: '物资类型',
prop: 'materailType',
hide: false,
search: true,
type: 'cascader',
dicData: materialTypes,
checkStrictly: true,
props: {
value: 'id',
label: 'dataName',
},
},
{
label: '物资编号',
prop: 'id',
},
{
label: '物资编号',
prop: 'name',
},
{
label: '生产厂家',
prop: 'producer',
},
{
label: '经销商',
prop: 'dealer',
},
// {
// label: '物资编号',
// prop: '',
// },
// {
// label: '物资编号',
// prop: 'id',
// },
// {
// label: '物资编号',
// prop: 'id',
// },
],
});
const actions = reactive([
{
auth: ({ row }) => row.type == '1',
name: 'custom',
icon: 'edit',
event: handleCustomFn,
},
{
name: '编辑',
icon: 'edit',
event: handleEdit,
},
{
type: 'danger',
name: '删除',
icon: 'delete',
event: handleDel,
},
]);
// #endregion
return { pageData, data };
/* ------ methods ------ */
// #region
async function getTypes() {
let res = await getMaterailTypes();
if (res.code == 200) {
materialTypes.push(...res.data);
console.log('types', materialTypes);
}
}
function getData() {
let params = {
currentPage: pageData.value.currentPage,
pageSize: pageData.value.pageSize,
type: currentType.value,
};
console.log('get params -- ', params);
if (currentType.value == '0') {
data.value = testData.map((v) => v);
} else {
data.value = testData.filter((item) => item.type == currentType.value);
}
console.log('data', data.value);
}
function handleSearch(form, done) {
if (!form.materailType || !form.materailType.length) {
currentType.value = '0';
} else {
currentType.value = form.materailType[0];
}
console.log('search --- ', form);
getData();
done();
}
function handleSearchReset() {
resetPage();
}
async function handleDialogClose(done) {
done();
console.log('dialog close');
}
/* 新建行数据 */
async function handleRowSave(form, done, loading) {
console.log('save', form);
loading();
}
/* */
function handleCustomFn({ row }) {
console.log('custom', row);
}
/* 行编辑 */
function handleEdit({ row }) {
console.log('edit', row);
}
/* 更新行数据 */
async function handleRowUpdate(form, done, loading) {
console.log('update', form);
loading();
}
/* 行删除 */
function handleDel({ row }) {
console.log('del', row);
}
function handleCurrentChange(val) {
pageData.value.currentPage = val;
getData();
}
function handleSizeChange(val) {
pageData.value.currentPage = 1;
pageData.value.size = val;
getData();
}
function resetPage() {
currentType.value = '0';
pageData.value.currentPage = 1;
pageData.value.pageSize = 10;
getData();
}
// #endregion
return {
curdRef,
_loading,
data,
pageData,
option,
actions,
handleSearch,
handleDialogClose,
handleRowSave,
handleRowUpdate,
handleSearchReset,
handleCurrentChange,
handleSizeChange,
};
};